Php 具有多个数据库的单例

Php 具有多个数据库的单例,php,singleton,multiple-databases,Php,Singleton,Multiple Databases,示例应用程序,包含员工信息,并由不同的应用程序(如payroll和pos)访问。我将员工数据放在一个数据库中,payroll数据和pos分别放在单独的数据库中 我有一个如下所示的数据库连接类,所以每次我想要连接到数据库时,我只需执行$conn=database::getInstance(db1) 工作很好,但基本上是超慢的。使应用程序运行非常缓慢。关于为什么会这样或更好的替代方案,有什么建议吗 任何帮助都将不胜感激 <?php class Database { pr

示例应用程序,包含员工信息,并由不同的应用程序(如payroll和pos)访问。我将员工数据放在一个数据库中,payroll数据和pos分别放在单独的数据库中

我有一个如下所示的数据库连接类,所以每次我想要连接到数据库时,我只需执行
$conn=database::getInstance(db1)

工作很好,但基本上是超慢的。使应用程序运行非常缓慢。关于为什么会这样或更好的替代方案,有什么建议吗

任何帮助都将不胜感激

<?php    
class Database {
        private $db;
        static $db_type;
        static $_instance;

        private function __construct($db){
            switch($db) {
                case "db1":
                  try{
                      $this->db = new PDO("mysql:host=" . DB_HOST . ";dbname=" . DB_NAME, DB_USER, DB_PASSWORD);
                  }
                  catch(PDOException $e){
                      print "Error!: " . $e->getMessage() . "<br />";
                      die();
                  }
                break;
                case "db2":
                  try{
                      $this->db = new PDO("mysql:host=" . DB_HOST_2 . ";dbname=" . DB_NAME_2, DB_USER_2, DB_PASSWORD_2);
                  }
                  catch(PDOException $e){
                      print "Error!: " . $e->getMessage() . "<br />";
                      die();
                  }
                break;
            }
            self::$db_type = $db;

        }

        private function __clone(){}

        static function getInstance($db_type){
            if(!(self::$_instance) || $db != self::$db_type){
                self::$_instance = new self($db_type);
            }
            return self::$_instance;
        }
    }
?>


将其更改为同时使用延迟加载怎么样。您不需要连接到承包商中的数据库。仅在第一次需要数据库时连接。这样,如果页面仅使用其中一个连接,则无需等待其他数据库。

不要不断创建新对象。所发生的事情是,每次您请求另一个数据库类型时,您都会通过new关键字重新创建它(尽管在没有看到使用此关键字的代码的情况下很难确认)

$\实例是一个静态成员,所以在更改数据库类型时会不断覆盖它。那么$db_类型是否适用于该问题

虽然这对于您正在做的事情来说是多余的(为什么不为每个DB设置两个变量?)

<?php    
class Database {
        private $db;
        static $db_types;


        private function __construct($db){
            switch($db) {
                case "db1":
                  try{
                      $db_types[$db] = new PDO("mysql:host=" . DB_HOST . ";dbname=" . DB_NAME, DB_USER, DB_PASSWORD);
                  }
                  catch(PDOException $e){
                      print "Error!: " . $e->getMessage() . "<br />";
                      die();
                  }
                break;
                case "db2":
                  try{
                      $db_types[$db] = new PDO("mysql:host=" . DB_HOST_2 . ";dbname=" . DB_NAME_2, DB_USER_2, DB_PASSWORD_2);
                  }
                  catch(PDOException $e){
                      print "Error!: " . $e->getMessage() . "<br />";
                      die();
                  }
                break;
            }


        }

        private function __clone(){}

        static function getInstance($db_type){
            if(!inarray($db_types[$db_type]){
                $db_types[$db_type] = new self($db_type);
            }
            return $db_types[$db_type];
        }
    }
?>

使用此设计。如果更改数据库,则会破坏与以前数据库的连接

为每个连接创建单独的对象,然后在连接对象之间切换

此外,出于同样的原因,这不是线程安全的。如果多个函数同时执行此操作,则一个函数可以在完成加载之前断开另一个函数


您确实应该为每个函数创建一个新的连接对象,而不是在函数或其他对象之间共享它。

检查DB\u HOST和DB\u HOST\u 2的值。之前,我发现MySQL使用“127.0.0.1”连接速度非常慢,但使用“localhost”立即连接


这取决于服务器的设置方式,但我只是认为这可能会有所帮助。

我不明白除了您不断切换连接之外,为什么这会让事情变得缓慢。这里我唯一能建议的是允许多个连接,而不是切换它们:

class Database {
   protected static $connections;

   protected $activeConnections = array();

   protected static $instance;

   protected function __construct() {

   }

   public static loadConnections(array $connections) {

      self::$connections = $connections;
   }

   public function getConnection($name)
   {
      if(!isset($this->activeConnections[$name]) {
          if(!isset(self::$connections[$name]) {
             throw new Exception('Connection "' . $name . '" is not configured.');
          }

           $this->activeConnections[$name] = new PDO(
              self::$connections[$name]['dsn'],
              self::$connections[$name]['username'], 
              self::$connections[$name]['password']
          ); 

      }

      return $this->activeConnections[$name];
   }
}

// usage

Database::loadConnections(array(
   'db1' => array(
       'dsn' => "mysql:host=" . DB_HOST . ";dbname=" . DB_NAME,
       'user' => DB_USER,
       'password' => DB_PASSWORD,
    ),
    'db2' => array(
       'dsn' => "mysql:host=" . DB_HOST2 . ";dbname=" . DB_NAME2,
       'user' => DB_USER2,
       'password' => DB_PASSWORD2,
)));

$conn1 = Database::getInstance()->getConnection('db1');
$conn2 = Database::getInstance()->getConnection('db2');
使用类似的方法,您实际上可以一次管理多个打开的连接,并且它们是延迟加载的-这意味着您在使用
Database::getConnection
请求PDO连接之前,不会实际实例化PDO连接。同样,您可以随时向其中注入额外的DSN和凭据。就我个人而言,我会将表单配置直接加载到类中,而不是在类中使用常量对其进行硬编码。然后你可以这样做:

// gives us an array
$config = Config::load('path/to/db/config.yml');

Database::loadConnections($config);

连接到数据库不会花费很长时间,我也不认为你的应用程序总体上会“慢”,因为你要连接到不同的数据库。数据库是本地的吗?或者在远程服务器上?数据库都是本地的。我目前使用的是这种方法,加载它需要相当长的时间,相比之下,当我将所有内容都放在一个数据库中时,您可以通过在某些行之前或之后捕获microtime()来帮助找到特定的行,从而减慢速度。如果您能特别将问题隔离到连接到数据库的线路上,则可能会有所帮助。抱歉,不确定您的意思,请您再解释一下。让我尝试一下,然后让您知道。已成功解决此问题,但未解决速度问题。仍然需要相当长的时间来加载。我想可能是其他原因导致了这个问题,但我会尝试prodigitalson的解决方案进行比较,然后我会知道让我尝试一下,并让你知道它是如何运行的,这是否缺少一个静态函数getInstance()?它不是一个完整的类。。。我刚刚概述了与你的不同之处:-)太棒了!将其改为包含对象的数组,效果非常好!供他人参考:
静态函数getInstance($db_type=”“){if(!isset(self::$connections[$db_type]){self::$connections[$db_type]=new self($db);}返回self::$connections[$db_type];}
@johnny-man对不起,已经快三年了。我都不记得了,哈哈。我想我在你的评论上面贴了些什么,但说实话,我甚至认不出来!已经有一段时间了。@user1239663不用担心。我忘了怎么回答一些问题。谢谢