【问题标题】:How do you manage database connections in php?你如何在 php 中管理数据库连接?
【发布时间】:2009-10-16 22:28:34
【问题描述】:

所以最近我真的开始积极使用php,我需要一些关于使用数据库连接的不同方法的见解。

一开始我只是用了简单的mysql_connect():

<?php
    $connection = mysql_connect(DB_HOST, DB_USER, DB_PASS) or die(mysql_error());
    mysql_select_db(DB_DB, $connection);
?>

过了一会儿,我创建了一个数据库类,我开始在每个文件中包含和初始化它 - 如下所示:

<?php
class MySQL_DB {

var $connection;

function MySQL_DB(){
    $this->connection = mysql_connect(DB_HOST, DB_USER, DB_PASS) or die(mysql_error());
    mysql_select_db(DB_DB, $this->connection);
}

function query($q){
    $res = mysql_query($q, $this->connection) or die(mysql_error());
    return $res;
}
}

$database = New MySQL_DB;
?>

这就是我当时正在使用的——它运行良好——但总有改进的方法。

所以我的问题是你如何管理你的数据库连接?

  • 你使用类吗?
  • 你的类包含什么(只是 连接甚至功能?)
  • 您推荐哪些做法?

【问题讨论】:

    标签: php oop database-connection connection-pooling


    【解决方案1】:

    我建议使用PDO。不要重新发明轮毂。这是many database engines 的一个很好的面向对象接口。 此外,我创建了一个仅初始化 PDO 对象的小函数。因此,所有连接设置都可以在一处更改。

    【讨论】:

      【解决方案2】:

      您当前的方法非常标准,并且效果很好。我用了很长时间。确实,像 PDO 这样的模块现在提供了这样的基本功能,这也非常好,可以让您摆脱自制代码的问题。

      不过,我在连接管理方面更进了一步。如果您进入一个复杂的应用程序,您可能会遇到有多个数据库或大量数据库使用的情况。包含单个数据库连接文件并具有全局 $database 变量对于多个数据库来说变得笨拙,并且对于可能不需要数据库连接的应用程序请求来说是不必要的。请记住,连接到数据库的成本很高。

      我所做的是创建一个为我处理数据库对象的单例 DatabaseManager 类,并确保不会实例化与给定数据库的多个连接。无需在应用顶部初始化新的数据库对象,您只需在每次需要该对象时调用 DatabaseManager。

      $db = DatabaseManager::getDatabase();
      

      这是我为 CodeIgniter 项目准备的示例类。您可以在getDatabase() 函数中看到它只是加载 CodeIgniter 的默认数据库对象,如果您不使用 CI,您可以将其替换为您自己的类(并为其运行连接例程)。这是一个非常简单的管理类,可以很容易地扩展为管理到不同数据库的多个连接。

      <?php
      
      /**
       * Implements the Singleton pattern to prevent multiple instantiations and connections
       * to the application database.
       *
       */
      class Database_manager
      {
          private static $instance;
          public $db;
      
          /**
           * Constructor function is declared private to prevent instantiation.
           *
           */
          protected function __construct()
          {
              parent::__construct();
          }
      
          /**
           * Returns an instance of a Database_manager.
           *
           * @return object Database_manager object
           */
          public static function getInstance()
          {
              if (self::$instance == null) {
                  $className = __CLASS__;
                  self::$instance = new $className();
              }
              return self::$instance;
          }
      
          public static function getDatabase()
          {
              $instance = self::getInstance();
              if ($instance->db == null) {
                  //utilize CodeIgniter's database loader
                  $instance->db = $instance->load->database('',true);
                  if (! is_object($instance->db)) throw new Exception("Could not load database.");
              }
              return $instance->db;
          }
      }
      

      也许我从使用这种连接管理方式中获得的最常见的优势是当我必须关闭应用程序以进行数据库维护时。通过在需要之前不实例化数据库连接,我可以轻松地在站点上放置“正在维护”消息(使正常的 MVC 调度短路),而不必担心在维护期间对应用程序打开数据库连接的请求进展。

      【讨论】:

        【解决方案3】:

        类的使用是提高自定义可重用性的方法。

        将所有通用实现引入类。你走在正确的轨道上。

        这个网站有以下干净的方法。
        该网站链接不再存在。 Archive Link.

        class connection {
            // Possible Modules are as follows:
            // DBX_MYSQL, DBX_ODBC, DBX_PGSQL, DBX_MSSQL, DBX_FBSQL, DBX_SYBASECT, DBX_OCI8, DBX_SQLITE
            private $module = DBX_MYSQL; 
        
            private $host = "localhost";
            private $database = "test";
            private $username = "testuser";
            private $password = "testpass";
        
            private $link;
            private $result;
            public $sql;
        
            function __construct($database=""){
                    if (!empty($database)){ $this->database = $database; }
                    $this->link = dbx_connect($this->module,$this->host,$this->database,$this->username,$this->password);
                    return $this->link;  // returns false if connection could not be made.
            }
        
            function query($sql){
                    if (!empty($sql)){
                            $this->sql = $sql;
                            $this->result = dbx_query($this->link,$sql,DBX_RESULT_UNBUFFERED);
                            return $this->result;
                    }else{
                            return false;
                    }
            }
        
            function fetch($result=""){
                    if (empty($result)){ $result = $this->result; }
                    return dbx_fetch_row($result);
            }
        
            function __destruct(){
                    dbx_close($this->link);
            }
        }
        

        【讨论】:

        • 我真的很喜欢这个的 fetch 功能——以及将结果保存为实例变量。感谢您的意见 +1
        • -1,对于未来的用户,永远不要将您的配置信息存储在同一个数据库类中。这是安全的,也破坏了可重用性。创建一个配置类/页面并使用常量或其他东西将它们传递给连接类。
        【解决方案4】:

        在您的数据库管理器示例中,您没有为您的类定义父级。 因此,调用 parent::__constructor() 会产生异常, 而且,你不能使用代码点火器的加载属性。

        您使用哪个类作为 DatabaseManager 的扩展?

        由于我不知道您将数据库管理器代码放在哪里,也不知道您将哪个类用作其父级,因此我通过让 getDatabase() 方法接收一个我称为 $loader 的输入参数来规避异常。 通常,这个 $loader 对象将是需要访问数据库的模型类。

        public static function getDatabase($loader)   
        {  
            $instance = self::getInstance();  
            if ($instance->db == null) {  
                    //utilize CodeIgniter's database loader  
                    $instance->db = $loader->load->database('default',true);  
                    if (! is_object($instance->db)) throw new Exception("Could not load database.");  
            }  
            return $instance->db;  
        }  
        

        最好的问候。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-01-24
          • 1970-01-01
          • 1970-01-01
          • 2019-05-11
          • 2016-07-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多