PHP数据库连接太多了

时间:2017-12-28 19:24:09

标签: php database pdo

在我的logout.php端点我使用了3个不同的类。这3个课程中的每一个都有:

private $conn;
private $table_name = "users";

// constructor with $db as database connection
public function __construct($db)
{
    $this->conn = $db;
}

此代码是为了从端点连接到数据库,同时初始化类,如下所示:

// include needed files
include_once '../config/database.php';
include_once '../classes/user.php';
include_once '../classes/token.php';

// instantiate database and product object
$database = new Database();
$db = $database->getConnection();

// initialize object
$user = new user($db);
$token = new token($db);

在某些函数的这三个类中,我有时需要使用其他类,所以我再次在 user 类中的logout函数中再次包含database class

public function logout($receivedToken)
{
    include_once '../config/database.php';
    include_once '../classes/token.php';

    // instantiate database
    $database = new Database();
    $db = $database->getConnection();

    $token = new token($db);
    if($token->checkToken($receivedToken))

我不确定这是否正确我调试我的代码并尝试重构它以使其更有意义。我是否需要在用户类的logout函数中再次包含此db以便使用令牌类?或者我可以以某种方式使用这种连接,我通过__construct而不是include数据库反复初始化端点?

1 个答案:

答案 0 :(得分:2)

这是一种糟糕的方法,首先,您只应在文件顶部include一次。

没有必要在logout方法中再次包含它,除了某些特定情况外,我认为方法体内的includes通常都是代码味道。

其次,在每次实例化Database类$database = new Database()并调用$database->getConnection()进行与数据库的新连接时,您将与数据库建立两个连接。您应该只实例化一次数据库,然后将其注入需要数据库连接的类(通过构造函数或作为方法参数传递)。

最后但并非最不重要,您应确保$database->getConnection()返回singleton

你可以这样做

<?php
    class Database
    {
        // specify your own database credentials
        private $host = "localhost";
        private $db_name = "obiezaca_db";
        private $username = "root";
        private $password = "";
        private $conn;
        // get the database connection

        public function getConnection()
        {
            if (!$this->conn) {
                try {
                    $this->conn = new PDO("mysql:host=" . $this->host . ";dbname=" . $this->db_name, $this->username, $this->password);
                    $this->conn->exec("set names utf8");
                } catch(PDOException $exception) {
                    // you shouldn't output exception error message in production
                    // because it can leak sensitive data such as DB username and password
                    echo "Database error";
                }
            }  
            return $this->conn;
        }
    }
?>

或者你可以成为像这样的Singletton工厂

<?php
    class Database 
    {
        // specify your own database credentials
        private $host = "localhost";
        private $db_name = "obiezaca_db";
        private $username = "root";
        private $password = "";

        private $conn;

        private static $instance;

        private function __construct() {};

        private function __clone() {};

        public static getInstance() 
        {
            if (!static::$instance) {
                static::$instance = new Database(); 
            } 
            return static::$instance;
        }

        // get the database connection
        public function getConnection()
        {
            if (!$this->conn) {
                try {
                    $this->conn = new PDO("mysql:host=" . $this->host . ";dbname=" . $this->db_name, $this->username, $this->password);
                    $this->conn->exec("set names utf8");
                } catch(PDOException $exception) {
                    // you shouldn't output exception error message in production
                    // because it can leak sensitive data such as DB username and password
                    echo "Database error";
                }
            }  
            return $this->conn;
        }
    }

 $database = Database::getInstance();
 $connection = $database->getConnection();

在这种方法中,无论您在代码中多少次调用这些方法,您都将获得相同的DatabasePDO个对象实例。

通过这种方式,您将确保始终与数据库建立一个连接,此外,您的数据库可以全局访问,因为它是静态访问的。