我是OOP (PHP)的新手,刚刚遇到了设计模式- singleton
。我发现了一个使用mysqli(单例类)的DB类。我添加了一些自定义方法(insert_id()
, query()
, fetch_result()
等)。
然后我创建了一个名为UserTools
的新类,我想扩展数据库类以使用我之前创建的方法(query()
, fetch_result()
等)。但是我得到这个错误:
致命错误:在(…)中调用私有数据库::__construct()当我尝试创建新类的实例(用户工具)。
我该怎么办?这是一个正确的结构吗?
有几种方法可以实现你想要的。
一个是:
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());
如果你真的很懒,你可以修改你的数据库类,把构造函数设为public:
class Database {
/* ... */
public function __construct(){/* ... */}
/* ... */
}
class UserTools extends Database {/* ... */}
但是我真的不建议你使用后者。这是非常糟糕的代码,从逻辑的角度来看,它没有意义。UserTools类使用一个数据库实例。不是数据库
我的理解是只有protected
和public
的方法和变量是通过扩展继承的,而不是私有的。尝试将您的方法/变量从private
更改为protected
。public
对所有人可见。
更多信息,参见:PHP可见性(手册)
编辑
理解单例模式。它被称为"单例",因为一个类只需要一个实例。因此,大多数实现单例模式的类都将构造函数定义为private,以限制创建多个构造函数。
为了创建一个单例的实例,大多数类定义了某种getInstance
静态方法,它是公共的。此公共方法调用私有构造函数,该构造函数可能会设置指示类已实例化的标志,以防止进一步尝试实例化该类。getInstance
方法返回调用构造函数的结果,本质上是类的实例。
你可以这样写
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
在大多数情况下,singleton模式通过将构造函数定义为private(即private function __construct()
)来防止singleton类的实例化。
因此,如果您尝试实例化您的自定义类或您正在扩展的原始类,您将获得上面的消息。你应该创建一个不同的类或定义和使用你的函数作为静态(如public static function query($sql, $dbconnection)
)。
见http://php.net/manual/en/language.oop5.patterns.php