【问题标题】:Singleton DB connectin with configuration file与配置文件的单例数据库连接
【发布时间】:2019-09-30 04:24:38
【问题描述】:

以下是我的连接代码,无需配置文件(.ini 文件)即可正常工作。但是如果我使用配置文件,我会收到错误:

致命错误: 常量表达式在第 13 行的 singletonDB.php 中包含无效操作。

但如您所见,变量$dsn$user$pass 不是静态变量。我不明白为什么我会收到非静态变量的静态变量相关错误。

我的最终目标是使用配置文件以及只保持与 DB 的单例连接。

<?php
$config = parse_ini_file("config.ini");
var_dump($config);
// Singleton to connect db.
class ConnectDb
{

    // Hold the class instance.
    private static $instance = null;

    private $pdo;

    private $dsn = $config['dsn_config'];

    private $user = $config['user_config'];

    private $pass = $config['password_config'];

    // The db connection is established in the private constructor.
    private function __construct()
    {
        echo nl2br("Inside constructor"); 
        $this->pdo = new PDO($this->dsn, $this->user, $this->pass);
        $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    }

    public static function getInstance()
    {
        if (! self::$instance) {
            self::$instance = new ConnectDb();
        }

        return self::$instance;
    }

    public function getConnection()
    {
        return $this->pdo;
    }
}

这是我的配置文件

;Local
dsn_config = 'mysql:host=127.0.0.1;port=3306;dbname=db_name;';
user_config = 'root';
password_config = 'root';

谢谢。

【问题讨论】:

    标签: php database configuration singleton


    【解决方案1】:

    问题不在于$dsn$user$pass,而是$config。你不能这样分配$config。如果将它们更改为字符串或其他值(int、array、bool),您会发现错误消失了:

    private $dsn  = false;  # All of these are 
    private $user = [];     # are valid
    private $pass = 1234;   # assignments
    

    那么问题是如何分配ini 参数?一种常见的方法是在实例化时注入到类的构造中:

    class ConnectDb
    {
        private static $instance = null;
    
        private $pdo;    
        private $dsn = '';
        private $user = '';
        private $pass = '';
    
        private function __construct($dsn, $user, $pass)
        {
            $this->dns = $dns;
            $this->user = $user;
            $this->pass = $pass;
    
            echo nl2br("Inside constructor"); 
            $this->pdo = new PDO($this->dsn, $this->user, $this->pass);
            $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        }
        ...etc.
    

    使用方法:

    <?php
    $config = parse_ini_file("config.ini");
    # Inject into the construct here
    $Db = new ConnectDb($config['dsn_config'], $config['user_config'], $config['password_config']);
    

    另一种方法可能是使用定义(常量):

    <?php
    $config = parse_ini_file("config.ini");
    # Create some defines
    define('DB_DSN', $config['dsn_config']);
    define('DB_USER', $config['user_config']);
    define('DB_PASS', $config['password_config']);
    

    然后该类将如下所示:

    class ConnectDb
    {
        private static $instance = null;
    
        private $pdo;
        private $dsn = '';
        private $user = '';
        private $pass = '';
    
        private function __construct()
        {
            # Assign the constants here ALTHOUGH...
            # I don't know that there is a good reason to make these class 
            # variables. I would just put the constants into the construct of
            # the PDO below. I don't know that you are going to need to reference
            # these variables after you have created the PDO connection.
            $this->dns = DB_DSN;
            $this->user = DB_USER;
            $this->pass = DB_PASS;
    
            echo nl2br("Inside constructor"); 
            $this->pdo = new PDO($this->dsn, $this->user, $this->pass);
            $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        }
        ...etc.
    

    【讨论】:

    • 感谢拉斯克拉特的详细解释。但是我不想在程序的其他地方创建对象。因此,根据您的解释,我只在构造函数中移动了配置文件读取代码。不知道这是否是一种好方法。
    • 是的,也可以。做这样的方法是有好处的。它类似于使用定义,因为您可以随时创建连接,而无需先解析 ini 并注入数组
    【解决方案2】:

    我不想在程序的其他地方创建对象,因此根据@Rasclatt 的解释,我将配置读取代码移到了构造函数中,现在它工作正常。以下是更新后的代码。

    文件名“singletonDB.php”

    <?php
    
    // Singleton to connect db.
    class ConnectDB
    {
    
        // Hold the class instance.
        private static $instance = null;
    
        private $pdo;
    
        private $dsn = '';
    
        private $user = '';
    
        private $pass = '';
    
        // The db connection is established in the private constructor.
        private function __construct()
        {
    //         $pdo = new PDO($dsn, $user, $password);
            $config = parse_ini_file("../config.ini");
            echo nl2br("var_dump ing config");
            var_dump($config);
    
            $this->dsn = $config['dsn_config'];
            $this->user = $config['user_config'];
            $this->pass = $config['password_config'];
    
            echo nl2br("Inside constructor"); 
            $this->pdo = new PDO($this->dsn, $this->user, $this->pass);
            $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        }
    
        public static function getInstance()
        {
            if (! self::$instance) {
                self::$instance = new ConnectDB();
            }
    
            return self::$instance;
        }
    
        public function getConnection()
        {
            return $this->pdo;
        }
    }
    

    稍后你可以得到连接表单 DB as

    require_once 'singletonDB.php';
    $instance = ConnectDB::getInstance();
    $conn = $instance->getConnection();
    var_dump($conn);
    

    但是我不确定这是否是一种好的编程方式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-05
      • 2010-12-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-26
      • 1970-01-01
      相关资源
      最近更新 更多