2011-10-04 99 views
0

我是OOP(PHP)的新手,剛剛遇到設計模式 - singleton。 我找到了一個使用mysqli(單例類)的DB類。我已經添加了一些自定義的方法(insert_id(),query()fetch_result()等)。PHP Singleton擴展類

然後我創建了一個名爲UserTools的新類,我想擴展數據庫類以使用之前創建的方法(query()fetch_result()等)。 但我得到這個錯誤:

Fatal error: Call to private Database::__construct() from invalid context in (...) when I try to create instance of the new class (User Tools).

我該怎麼辦?這是一個正確的結構嗎?

+0

單身===做錯了。它是一個糟糕的設計模式,應該始終避免。 – Raynos

回答

1

有幾種方式來實現你想要什麼。

其中之一是:

class UserTools { 
    private $db; 
    function __construct() { 
     $this->db = Database::db_connect(); 
    } 

    function login() { /* ... */} 
} 

雖然這將是更好的數據庫實例直接傳遞給構造函數是這樣的:

class UserTools { 
    private $db; 
    function __construct($db) { 
     $this->db = $db; 
    } 

    function login() { /* ... */} 
} 

// Usage 
$userTools = new UserTools(Database::db_connect()); 

如果你真懶,你可以只修改數據庫類和公共構造函數:

class Database { 
    /* ... */ 
    public function __construct(){/* ... */} 
    /* ... */ 
} 

class UserTools extends Database {/* ... */} 

但我真的不鼓勵你使用後者。這是非常糟糕的代碼,從邏輯的角度來看它沒有任何意義。您的UserTools類使用一個數據庫實例。它是而不是一個數據庫。

+0

如果我使用第二個,是否創建了數據庫類的新實例? (它工作正常,順便說一句,謝謝) –

+1

編號由於'數據庫'是一個單身人士,它將始終返回相同的實例。 – Alfwed

+0

非常感謝!這是我的一天。 = d –

0

你可以寫類似

class UserTools extends DB { 
    .... 
} 

一個簡單的例子就繼承在PHP中:

class A { 
    public $a; 
    public function set_a($new_a) { $this->a = $new_a; return $this; } 
    public function get_a() { return $this->a; } 
} 

class B extends A { 
    public $b; 
    public function set_b($new_b) { $this->b = $new_b; return $this; } 
    public function get_b() { return $this->b; } 
} 

$objb = new B(); 

$objb->set_a("Some Value")->get_a(); //Some Value 
+0

我做到了。但我想在它做這樣的事情: 公共功能登錄($ un,$ pass){ //在這裏使用一個DB的方法? } –

+0

'extends'關鍵字將導致所有函數和實例變量從父類('DB')類繼承到子類'UserTools'類,您可以(也應該)另外添加更多類! –

+0

你確定擴展一個DB單例的User類是正確的嗎?邏輯上,特別是 –

1

這是我的理解,只有protectedpublic方法和變量通過擴展繼承,而不是私人的。嘗試將您的方法/變量從private更改爲protectedpublic對所有人都是可見的。

欲瞭解更多信息,請參見:PHP Visibility (Manual)

編輯

瞭解Singleton模式。它被稱爲'單身人士',因爲只有一個類的實例預計。因此,大多數實現單例模式的類將構造函數定義爲私有的,以限制您創建多個類。

要創建一個單例的實例,大多數類定義了某種getInstance靜態方法,它是公共的。這個公共方法調用私有構造函數,該構造函數可能會設置標誌,指​​示該類已被實例化,以防止進一步嘗試實例化該類。 getInstance方法返回調用構造函數的結果,實質上是類的實例。

+0

+1這就是錯誤說 – Xeoncross

+0

好吧,我張貼從我的代碼下面的鏈接(pastebin鏈接)。屬性和構造函數是私有的,其他的都是公共的。 但我不明白一個瘦。當我擴展課程時,我是否會創建一個新實例? –

+0

不。您在定義類時擴展了一個類。在使用關鍵字'new'之前,您不要創建一個類的實例。想象一下,爲建築物採取一套藍圖,並用透明膠帶爲另一個房間添加藍圖。當你使用'new'關鍵字時,你實際上'建造'了建築物。 –

0

在大多數情況下,單例模式通過將構造函數定義爲私有(即private function __construct())阻止實例化Singleton類。

所以,如果您嘗試實例化您的自定義類或您正在擴展的原始類,您將獲得上述消息。您應該創建一個不同的類或定義並使用您的函數作爲靜態(例如public static function query($sql, $dbconnection))。

http://php.net/manual/en/language.oop5.patterns.php