通过PHP类连接MySQL数据库的单个实例


Single instance of a MySQL database connection via PHP Class

我有以下数据库类。我的想法是,这将检查类的现有实例并返回,而不是创建新的数据库连接。

当我运行代码时,它创建一个连接。当我刷新页面时,另一个连接被创建(检查MySQL连接)。

我的想法不正确吗?对使用OOP相当陌生,所以对新手的问题表示歉意!

如有任何帮助或指点,我将不胜感激。

许多谢谢。

<?php
class Db
{
    private $_connection;
    private static $_instance; 
    private $_host = 'localhost';
    private $_username = 'root';
    private $_password = 'password';
    private $_database = 'test';
    public static function getInstance()
    {
        if (!self::$_instance) {
            self::$_instance = new self();
        }
        return self::$_instance;
    }
    private function __construct()
    {
        try {
            $this->_connection  = new PDO("mysql:host=$this->_host;dbname=$this->_database", $this->_username, $this->_password); 
            echo 'Connected to database';
        } catch (PDOException $e) {
            echo $e->getMessage();
        }
    }
    private function __clone()
    {
    }
    public function getConnection()
    {
    return $this->_connection;
    }
}
$db = Db::getInstance();

PHP是一个"无共享"的环境。PHP应用程序处理的每个请求都作为单独的线程或单独的进程与所有其他请求隔离,这取决于所使用的服务器api (SAPI)。您所设计的类是单例的,但它被隔离到单个请求-响应周期。这意味着如果您在单个请求中调用Db::getInstance() 10次,您将获得对同一对象的10个引用,但是在单独的请求中单独调用将创建并返回一个不同的对象。

您可以在服务器端或应用程序端使用某种类型的连接池来减少对后端数据库服务器的并发连接的数量。PHP的PDO抽象通过PDO::ATTR_PERSISTENT连接驱动程序选项启用应用程序端连接池。这些连接池缓存在PHP父进程中,而不是缓存在处理请求并随后重用的工作线程/进程中。根据SAPI和底层数据库类型,打开的连接的确切数量以及共享连接的方式是可变的。

在使用PHP作为服务器端语言时,了解后台发生的事情可能是一件好事。

当您运行该代码时,

PHP为您启动连接。它不会在页面加载后将连接持久化。

在每次页面加载时,将打开新的连接,以便您可以继续发出请求并执行任务。

考虑如果发生了会发生什么。您关闭页面并进入睡眠状态,服务器将永远与数据库保持打开的连接。你有一些访问者,然后你达到了连接限制,得到一个过多的连接错误。

可能有一些参考文献可以引用,但我真的找不到很多,因为这更像是一个逻辑问题,而不是一个编码问题。

每次刷新页面时,您都在实例化一个全新的Db对象,并将其分配给一个名为$ Db的全新变量,因此每次都可以获得连接。我也认为你可能使你的Db类过于复杂了。

当我创建db类来包装PDO或mysqli时,想法是创建一个db对象,当实例化时将包含数据库连接作为其属性之一。为了实现这一点,我将稍微重写一下您的类。像这样的东西将是所有你需要创建一个私有连接的Db对象,它可以被任何你想添加到类的其他方法使用…例如,一个发出查询的方法,

class Db
{
    private $_connection;
    private $_host = 'localhost';
    private $_username = 'root';
    private $_password = 'flindersbeast';
    private $_database = 'flinders';
    public function __construct()
    {
        try {
            $this->_connection = new PDO("mysql:host=$this->_host;dbname=$this->_database", $this->_username, $this->_password); 
            echo 'Connected to database';
        } catch (PDOException $e) {
            echo $e->getMessage();
        }
    }
    // Other methods here will use $this->_connection to do a variety of things.
    public function example()
    {
     // Do stuff - as needed you can pass $this->_connection to PDO 
    }
}
$db = new Db;

祝你好运!