PHP单例扩展类


PHP Singleton extending class

我是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类使用一个数据库实例。不是数据库

我的理解是只有protectedpublic的方法和变量是通过扩展继承的,而不是私有的。尝试将您的方法/变量从private更改为protectedpublic对所有人可见。

更多信息,参见: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