PDO отказывается переключаться между несколькими базами данных!
Пожалуйста, я новичок в PDO, а также новичок в PHP. В настоящее время я работаю над проектом, который включает соединения со многими базами данных: MySQL, MSSQL и Oracle. Поэтому я использую класс ниже, с PDO, для моего соединения. Код класса ниже.
class db {
private static $objInstance; /* * Class Constructor - Create a new database connection if one doesn't exist * Set to private so no-one can create a new instance via ' = new DB();' */ private function __construct() {} /* * Like the constructor, we make __clone private so nobody can clone the instance */ private function __clone() {} /* * Returns DB instance or create initial connection * @param * @return $objInstance; */ public static function getDB($DBtype, $DBindex) { include('vars.inc.php'); if (!self::$objInstance){ $DBid = $DBindex - 1; switch ($DBtype){ case "mysql": self::$objInstance = new PDO("mysql:host=".$dbvars[$DBid][0].";dbname=".$dbvars[$DBid][1], $dbvars[$DBid][2], $dbvars[$DBid][3]); break; case "mssql": self::$objInstance = new PDO("odbc:Driver={SQL Server};Server=".$dbvars[$DBid][0].";Database=".$dbvars[$DBid][1], $dbvars[$DBid][2], $dbvars[$DBid][3]); break; case "oci"; self::$objInstance = new PDO("oci:dbname=//".$dbvars[$DBid][0].":".$dbvars[$DBid][4]."/".$dbvars[$DBid][1], $dbvars[$DBid][2], $dbvars[$DBid][3]); break; // Add other case(s) here if another RDBMS (Relational Database Management system) is used default: break; } self::$objInstance-> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } return self::$objInstance; }
}
И вот файл включения vars, который требуется классу, я использовал массив, потому что я чувствовал, что новые базы данных могут быть легко добавлены непрограммистом в файл со временем. Конечно, здесь я изменил значения файла var.
define ('DB_SERVER', 'localhost'); define ('DB_NAME', 'db1name'); define ('DB_USER', 'root'); define ('DB_PASSWORD', 'rootpass'); define ('DB_PORT', ''); define ('DB2_SERVER', 'xxx.xxx.xx.xxx'); define ('DB2_NAME', 'db2name'); define ('DB2_USER', 'root2'); define ('DB2_PASSWORD', 'rootpass2'); define ('DB2_PORT', ''); define ('DB3_SERVER', 'xx.xxx.xxx.xxx'); define ('DB3_NAME', db3name '); define ('DB3_USER', 'root3'); define ('DB3_PASSWORD', 'rootpass3'); define ('DB3_PORT', ''); define ('DB4_SERVER', 'xxx.xx.xxx.xx'); define ('DB4_NAME', 'oracledb'); define ('DB4_USER', 'root4'); define ('DB4_PASSWORD', 'rootpass4'); define ('DB4_PORT', '1521'); $ dbvars = array (массив (DB_SERVER, DB_NAME, DB_USER, DB_PASSWORD, DB_PORT), массив (DB2_SERVER, DB2_NAME, DB2_USER, DB2_PASSWORD, DB2_PORT), массив (DB3_SERVER, DB3_NAME, DB3_USER, DB3_PASSWORD, DB3_PORT), массив (DB4_SERVER, DB4_NAME, DB4_USER, DB4_PASSWORD, DB4_PORT));Теперь проблема в том, что всякий раз, когда я подключаюсь к одной базе данных и пытаюсь выполнить свои запросы к другой, PDO постоянно запоминает старую базу данных. Но если я независимо запускаю любой запрос, все в порядке. Может кто-нибудь помочь с этим, или предложить лучший метод?:(
Например
include('./includes/db.class.php'); try { $result = DB::getDB("mysql", 3)->query("SELECT myrow FROM mytable");
foreach($result as $row){ print $row['myrow'].'<br />'; } }catch(PDOException $e){ echo $e->getMessage(); } echo "<br />Then<br /><hr /><br />"; try { $result = DB::getDB("mysql", 1)->query("SELECT yourrow FROM yourtable"); foreach($result as $row){ print $row['yourrow'].'<br />' ; } }catch(PDOException $e){ echo $e->getMessage(); }
В этом случае PDO будет просто проверять DATABASE db1name для таблицы TABLE yourtable, а не проверять DATABASE db3name. Поэтому PDO выдаст ошибку:
SQLSTATE [42S02]: Базовая таблица или представление не найдено: 1146 Таблица "db1name.yourtable" не существует
2 ответа
Вы настроили его как синглтон. Итак, ваш следующий звонок Db::getDB
возвращает исходный экземпляр Если вы хотите кэшировать экземпляры на время выполнения сценария, измените $objInstance
в массив, а затем вместо того, чтобы делать:
if (!self::$objInstance){
Делать
$signature = $DBtype . $DBindex;
if (!isset(self::$objInstances[$signature])) {
Конечно, вам нужно изменить строки назначения и строку возврата, но я думаю, вы поняли...
Похоже, что ваша функция getDB будет подключаться только один раз из-за этой строки:
if (!self::$objInstance){
Поэтому при первом его выполнении он будет подключаться, но при всех последующих вызовах логика игнорируется.
Я предлагаю добавить другое свойство в ваш класс, в котором хранится текущий DBType, и изменить ваше условное выражение на:
if (!self::$objInstance || $DBtype != self::$dbtype){
Вы должны будете установить $dbtype внутри каждого случая оператора switch.