【问题标题】:Any simpler / better way of making a mysql singleton db class in php?在php中制作mysql单例数据库类的任何更简单/更好的方法?
【发布时间】:2010-01-07 05:38:27
【问题描述】:

这是我正在使用的:

<?php
final class Database {
    private static $oDb;
    public static function init() {
        if(self::$oDb == NULL)
        {
            self::$oDb = mysql_connect('localhost', 'mysql_user', 'mysql_password') or die(mysql_error());
            mysql_select_db('mysql_db_name', self::$oDb) or die (mysql_error());;
        }
        return self::$oDb;
    }
    public function query($sql)
    {
        return mysql_query($sql) or die(mysql_error());
    }
}
?>

用法:

$oDb = Database::init();
$sql = foo;
$oDb->query($sql);

假设我只希望它连接并执行这一个查询功能,我应该对这个类进行任何改进吗?内存还是代码效率?

另外,有没有一种有效的方法可以从配置文件中获取数据库凭据?我知道我不能在课堂上使用包含。

【问题讨论】:

  • 为什么不能在课堂内使用包含?没有技术上的原因,你不能从编码实践中尝试避免它。
  • 我认为他认为你不能在函数之外使用它......
  • 我的配置文件只是一组define("name", "value");。无需解析。

标签: php mysql class singleton


【解决方案1】:

我通常在这种情况下使用惰性初始化,并且只有一个公共方法(在这种情况下),并带有一个私有构造函数来防止外部实例化(根据单例模式):

class Database {
  private static $instance;
  private $conn;

  private function Database() {
    // do init stuff
    require_once('dbconfig.php'); // contains define('DB_USER', 'webuser'); etc...
    $this->conn = mysql_connect(DB_HOST, DB_USER, DB_PASS); // do error checking
  }

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

  public static function query($sql) {
    $instance = self::getInstance();
    return mysql_query($sql, $instance->conn);
  }
}

然后您可以在需要使用它的任何时候致电$dbHandle = Database::getInstance()。或者在这种情况下,由于定义了静态查询方法,因此您可以使用 Database::query("select * from xx;"); 而无需调用任何类型的 init。

【讨论】:

  • 在相对路径上没有那个 require_once 意味着如果我将类文件本身包含在不同的目录中,它会中断吗?就像在 index.php 与 admin/index.php 中包含 'db.class.php'
  • 通常,我将使用 dirname() 样式函数定义一个 ROOT_DIR 或一些此类变量,以获取指向我网站根目录的绝对路径,然后我会使用类似 require_once(ROOT_DIR.'/config/db.config.php'); 的东西。这样,获取配置时当前目录在哪里都没有关系。
  • 我可能要求太多了,但是当我尝试使用您的课程时,我遇到了一个错误的兔子洞。在“公共静态”行中添加了“功能”,然后我在对象上下文之外使用 $this 时遇到错误。有什么想法吗?
  • 对不起,我实际上并没有尝试运行它,所以我错过了一些语法错误。我已经编辑了帖子并对其进行了测试;现在可以了。 $this-&gt;instance 在公共静态方法中应该是 self::$instance
  • 这是古老的,但对于后代来说,简单地使用内置的 __DIR__ 常量比保持 ROOT_DIR 变量更容易。假设您的 db 类位于 root 的子目录中。然后你可以调用 require_once(__DIR__.'/../config/db.config.php');
【解决方案2】:

这很简单,可以正常工作。

您可以将您的凭据传递给 init();

include(config.php);
$oDb = Database::init( DB_HOST, DB_NAME, DB_USER, DB_PASSWORD );
$sql = foo;
$oDb->query($sql);

【讨论】:

    【解决方案3】:

    您可以在类中的函数内使用包含

    <?php
    final class Database {
        private static $oDb;
        public static function init() {
            if(self::$oDb == NULL)
            {
                include('config.php')
                self::$oDb = mysql_connect(DB_HOST, DB_USER, DB_PASS) or die(mysql_error());
                mysql_select_db(DB_NAME, self::$oDb) or die (mysql_error());;
            }
            return self::$oDb;
        }
        public function query($sql)
        {
            return mysql_query($sql) or die(mysql_error());
        }
    }
    ?>
    

    或者你可以只传递变量...

    <?php
    final class Database {
        private static $oDb;
        public static function init($host, $user, $pass, $name) {
            if(self::$oDb == NULL)
            {
                self::$oDb = mysql_connect($host,$user,$pass) or die(mysql_error());
                mysql_select_db($name, self::$oDb) or die (mysql_error());;
            }
            return self::$oDb;
        }
        public function query($sql)
        {
            return mysql_query($sql) or die(mysql_error());
        }
    }
    ?>
    

    或者您可以将凭据存储在 php.ini 文件中

    <?php
    final class Database {
        private static $oDb;
        public static function init($db_name) {
            if(self::$oDb == NULL)
            {
                self::$oDb = mysql_connect() or die(mysql_error());
                mysql_select_db($db_name, self::$oDb) or die (mysql_error());;
            }
            return self::$oDb;
        }
        public function query($sql)
        {
            return mysql_query($sql) or die(mysql_error());
        }
    }
    ?>
    

    php.ini 文件:

    mysql.default_host="host"
    mysql.default_user="user"
    mysql.default_password="password"
    

    【讨论】:

      【解决方案4】:

      对于单例类,Dan Breen 遵循的模型是最干净且非常常见的。但是,在这种情况下,我还允许 getInstance 方法接受一些参数,以便您可以在实例化时覆盖默认配置,或者只获取引用而不创建连接(这两种用例都会不时发生)。

      数据库.php

      require_once("../path/to/config/database.php");
      
      class Database {
        private static $instances = array();
      
        private function Database($host, $user, $password, $name) {
          // do init stuff
        }
      
        public static getInstance(
          $host=DB_HOST, $user=DB_USER, $password=DB_PASSWORD, $name=DB_NAME
        ) {
          $key = strtolower($host . $user . $password . $name);
      
          if ( !$self::instances[$key] ) {
            $self::instances[$key] = new Database($host, $user, $password, $name);
          }
          return $self::instances[$key];
        }
      }
      

      ..config/database.php:

      define("DB_HOST", "localhost");
      define("DB_USER", "mrsqlguy");
      define("DB_PASS", "!!!");
      define("DB_NAME", "just_another_wordpress");
      

      编辑:我已将其更改为更像一个享元,以确保您只为每个连接位置/数据库获取一个实例。这解决了您的顾虑并保持了一定程度的灵活性。

      【讨论】:

      • 灵活很好,我喜欢这个答案,但一个潜在的问题是,由于它只初始化一次,以后可能会导致非常奇怪的问题。也就是说,如果程序员使用一些新的连接参数调用 getInstance,但在其他地方已经使用不同的参数进行了初始调用,那么可能很难确定它没有使用第二次传递的参数。
      猜你喜欢
      • 1970-01-01
      • 2019-03-25
      • 1970-01-01
      • 1970-01-01
      • 2011-08-04
      • 2011-06-14
      • 1970-01-01
      • 2017-08-14
      • 2020-10-15
      相关资源
      最近更新 更多