【问题标题】:Danger of Declaring Multiple Database Connections in Public __Constructor vs Static Variable Connection在公共 __Constructor 与静态变量连接中声明多个数据库连接的危险
【发布时间】:2020-12-21 01:52:20
【问题描述】:

我最近开始通过使用更多继承来更新我在 Apache 服务器上的 Api 代码。由于缺乏经验,我过去使用它有点小心。
问题是我注意到为每个模型实例设置了一个新的数据库连接。所以我在Static 变量上创建了一个替代连接以传递给每个模型。我的问题是,如果我在下面的示例中使用__construct 创建连接,每个新模型实例上的多个数据库连接会导致问题吗?

     class ApiEnterprises {
        protected $db;

        private $table;
        public function __construct(){
            $this->messager = new Messager();
            $this->table = 'enterprisetable';
            $this->db = new \mysqli(DB_HOST, DB_USERRW, DB_PASSWRW, DB_DBASE);
            if ($this->db === NULL || !$this->db) {
                // set response code
                echo $this->messager->databaseFailed();
            }
        }
    }

    class ApiUsers {
        protected $db;

        private $table;
        public function __construct(){
            $this->messager = new Messager();
            $this->table = 'usertable';
            $this->db = new \mysqli(DB_HOST, DB_USERRW, DB_PASSWRW, DB_DBASE);
            if ($this->db === NULL || !$this->db) {
                // set response code
                $this->messager->databaseFailed();
            }
        }
   }

另外,Static 变量会更安全吗?因为我可以在 Controller __destruct 方法中删除它。

    class Database {
        static $connect;

        protected static function conn() {
             self::$connect = new \mysqli(DB_HOST, DB_USERRW, DB_PASSWRW, DB_DBASE);
            return self::$connect;
        }
    }

    class ApiUserController extends Database {
        private $user_model;
        private $enterprise_model;
        public $connection;
        public function __construct($data){
            $this->connection =  parent::conn();
            //pass connection to models
            $this->user_model = new ApiUsers($this->connection);
            $this->enterprise_model = new ApiEnterprises($this->connection);
        }
    }

【问题讨论】:

标签: php inheritance mysqli


【解决方案1】:

您需要的是IoC container,但在您到达那里之前,您需要以这样一种方式设计您的模型,即它们接受数据库实例作为构造函数中的参数。这称为依赖注入。所有依赖实例在实例化时都被注入到新对象中。

由于您的Database 没有用,我不建议您使用它,但您应该编写一些数据库抽象库或使用网络上已有的库。例如EasyDB

这里是一个单一依赖注入的例子:

class ApiEnterprises {
    protected $db;
    protected $messager;

    private $table = 'enterprisetable';

    public function __construct(mysqli $db, Messager $messager) {
        $this->db = $db;
        $this->messager = $messager;
    }
}

// mysqli connection somewhere at the start of your application
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new \mysqli(DB_HOST, DB_USERRW, DB_PASSWRW, DB_DBASE);
$mysqli->set_charset('utf8mb4'); // always set the charset

// instantiate the model and pass mysqli as an argument
$enterprise = new ApiEnterprises($mysqli, $messager);

【讨论】:

  • 为什么说Database类没用呢?在我的两个示例中,第二个使用dependency injection,您可以清楚地看到连接实例已传递给模型。 //pass connection to models $this->user_model = new ApiUsers($this->connection); $this->enterprise_model = new ApiEnterprises($this->connection);。也感谢您的回答,因为我现在知道第二个示例是两者中更好的一个。
  • 是的,您的第二个示例使用依赖注入,但控制器类继承自数据库类。当子类是一般情况的特定情况时,应该发生不继承,例如沃尔沃卡车继承自车辆。控制器不是数据库类,因此不应继承。此外,看起来您的数据库类没有做任何事情。请记住,mysqli 本身就是一个类,除非您打算使用其他功能对其进行扩展,否则您不需要包装它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-05-26
  • 1970-01-01
  • 2013-06-17
  • 2017-05-31
  • 2014-04-10
  • 2013-10-22
  • 2017-11-17
相关资源
最近更新 更多