单例模式不适用于多个数据库

时间:2017-05-18 09:01:44

标签: php design-patterns pdo singleton

我有两个db,我想从我的Db类中返回其中一个,这实际上是Singleton模式。所以我不想每次都建立新的连接,而是检查数组中是否存在连接,然后返回它。问题是我只从getInstance方法返回的东西是同一个Db对象而不是PDO对象?

  class Db
{
    public static $dbTypes = [];

/**
 * Db constructor.
 * @param $db
 */
private function __construct($db)
{
    switch ($db) {
        case ConfigManager::getDbDatabase(true):
            try {
                self::$dbTypes[$db] = new \PDO("mysql:host=" . ConfigManager::getDbHost(true) . ";dbname=" . ConfigManager::getDbDatabase(true) . ";charset=utf8", ConfigManager::getDbUser(true), ConfigManager::getDbPass(true));
            } catch (\PDOException $ex) {
                echo $ex->getMessage();
            }
        break;
        case ConfigManager::getDbDatabase(false):
            try {
                self::$dbTypes[$db] = new \PDO("mysql:host=" . ConfigManager::getDbHost(false) . ";dbname=" . ConfigManager::getDbDatabase(false) . ";charset=utf8", ConfigManager::getDbUser(false), ConfigManager::getDbPass(false));
            } catch (\PDOException $ex) {
                echo $ex->getMessage();
            }
        break;
    }

}

/**
 * @throws \Exception
 */
private function __clone()
{
    throw new \SoapFault('CODE_ERROR', 'You can not clone ' . __CLASS__ . ' class.');
}

/**
 * @param $db
 * @return \PDO
 */
public static function getInstance($db) : \PDO
{
    if (!array_key_exists($db, self::$dbTypes)) {
        self::$dbTypes[$db] = new self($db);
    }
    return self::$dbTypes[$db];

}

}

不要让ConfigManager类让您感到困惑,它只是一个从配置文件中获取值的getter类。基本上,如果ConfigManager方法中的参数是返回第一个db的真值,并且如果它是false,则返回第二个db的值。我想像这样使用PDO:

  $this->db = Db::getInstance(ConfigManager::getDbDatabase(true));
  $query = $this->db->prepare("SELECT c.extern_username...

我得到"调用未定义的方法Helpers \ ConfigHelpers \ Db :: prepare()"错误。请指教。

1 个答案:

答案 0 :(得分:0)

我找到了解决方案。我添加了新的非静态属性,并在switch case之后将该属性追加到数组,然后从getInstance方法返回它。

class Db
{
private static $dbTypes = [];
private $pdo;

/**
 * Db constructor.
 * @param $db
 */
private function __construct($db)
{
    switch ($db) {
        case ConfigManager::getDbDatabase(true):
            try {
                $this->pdo = new \PDO("mysql:host=" . ConfigManager::getDbHost(true) . ";dbname=" . ConfigManager::getDbDatabase(true) . ";charset=utf8", ConfigManager::getDbUser(true), ConfigManager::getDbPass(true));
            } catch (\PDOException $ex) {
                echo $ex->getMessage();
            }
        break;
        case ConfigManager::getDbDatabase(false):
            try {
                $this->pdo = new \PDO("mysql:host=" . ConfigManager::getDbHost(false) . ";dbname=" . ConfigManager::getDbDatabase(false) . ";charset=utf8", ConfigManager::getDbUser(false), ConfigManager::getDbPass(false));
            } catch (\PDOException $ex) {
                echo $ex->getMessage();
            }
        break;
    }
    self::$dbTypes[$db] = $this->pdo;
}

/**
 * @throws \Exception
 */
private function __clone()
{
    throw new \SoapFault('CODE_ERROR', 'You can not clone ' . __CLASS__ . ' class.');
}

/**
 * @param $db
 * @return \PDO
 */
public static function getInstance($db) : \PDO
{
    if (!array_key_exists($db, self::$dbTypes)) {
        self::$dbTypes[$db] = new self($db);
    }
    return self::$dbTypes[$db]->pdo;

}
}

然后你就像这样称呼它

$this->db = Db::getInstance(ConfigManager::getDbDatabase(true));

并像这样使用

$query = $this->db->prepare("SELECT c.e...