【问题标题】:Singleton pattern doesn't work with multiple db's单例模式不适用于多个数据库
【发布时间】:2017-05-18 09:01:43
【问题描述】:

我有两个数据库,我想从我的 Db 类中返回其中一个,这实际上是单例模式。所以我不想每次都建立新的连接,而是检查数组中是否存在连接然后返回它。问题是我从 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 方法中的参数为 true,则返回第一个 db 的值,如果为 false,则返回第二个 db 的值。我想像这样使用 PDO:

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

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

【问题讨论】:

  • 你试过 var_dumping $this->db 吗?可能它不是 PDO 实例。还有 ConfigManager::getDbDatabase(true) 返回什么?
  • 我在 phpstorm 中调试它,$this->db 是一些无穷无尽的数组,如果参数为真,则 ConfigManager::getDbDatabase(true) 返回第一个数据库名称,如果参数为假,则返回第二个数据库名称。所有其他 ConfigManager 方法的工作方式相同。
  • 当我执行 error_log("Db return value " . var_export($this->db, true)); 时,我在日志文件中得到 Helpers\\ConfigHelpers\\Db::__set_state(array(\n))

标签: php design-patterns pdo singleton


【解决方案1】:

我找到了解决方案。我添加了新的非静态属性,并在 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...

【讨论】:

    猜你喜欢
    • 2012-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-04
    • 2019-11-13
    • 1970-01-01
    • 1970-01-01
    • 2019-11-16
    相关资源
    最近更新 更多