使用php7.0运行的单例数据库类的继承问题


Inheritance issue with singleton database classes running with php 7.0

所以在php5.*版本中,我会将构造函数设置为私有的,然后只获取它的实例,这很好,内存使用率很低。

class bsdb extends mysqli {
    private $host = '';
    private $account = '';
    private $password = '';
    private $database = '';
    private static $instance;
    private function __construct(){
        try {
            parent::__construct($this->host, $this->account, $this->password, $this->database);
            parent::set_charset('utf8');
        } catch (mysqli_sql_exception $e) {
            log(sprintf("Connect failed: %s'n", mysqli_connect_error()), 'sql');
            die('DB Connection error');
        }
    }
    static function instance() {
        if (!self::$instance)
                self::$instance = new bsdb;
            return self::$instance;
    }
}

但在php7中,我再也不能这样做了,因为如果我从具有公共构造函数的类继承,php的第7版不允许我将构造函数设为私有。这给我带来了一个错误。

所以我的问题是,在php的新版本中,最好的方法是什么?

在您的问题中,您将问题的根源描述为:

但在php7中,我再也不能这样做了,因为如果我从具有公共构造函数的类继承,php的第7版不允许我将构造函数设为私有。这给我带来了一个错误。

PHP 7会给您带来致命错误,这是正确的,类似于以下带有私有ctor的Bar从带有公共ctor的Foo扩展而来的错误:

致命错误:对Bar::__construct()的访问级别必须是公共的(如在Foo类中)

然而,您造成了一种错误的印象,认为这应该在PHP5中起作用,并且自PHP7以来才被禁止。请放心,事实并非如此。

方法的可见性(包括构造函数方法)已经在PHP5中引入,自第一个PHP5发布以来,您会遇到致命错误。看看它在今天许多甚至不受支持的PHP版本中的作用:https://3v4l.org/pfcBm

由于可见性是自版本5以来语言的一部分,我看不出这是PHP7的问题,但仅适用于非常特定的类mysqli

但是,您不需要将ctor设为私有。您所需要的只是单个实例,而不是单例模式的实现。一个快速的缓解方法是公开ctor,只需使用bsdb::instance()全局静态方法即可获得特定的bsdb实例。从问题中可以看出,该类的主要职责是管理该全局静态方法中的全局变量,并使数据库配置属性具有常数值。

我通常认为,您呈现的类一次做得太多了(实例创建和生命周期管理、数据库配置处理,最后但同样重要的是,它是一个mysqli),在变化的时候,这通常是一种负担,通常仅此一点就是一个很好的例子,说明为什么您应该将不属于一起的东西分开。

stackoverflow上的经典读物可能会帮助您更好地识别和重新思考您的单身需求:

  • 在PHP中,是否存在具有数据库访问权限的singleton用例