2010-08-19 4 views
2

Пожалуйста, я очень новичок в PDO, а также новичок на PHP. В настоящее время я работаю над проектом, который включает подключения ко многим базам данных: MySQL, MSSQL и Oracle. Поэтому я использую класс ниже, с PDO, для моего подключения. Код класса приведен ниже.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(array(DB_SERVER, DB_NAME , DB_USER, DB_PASSWORD, DB_PORT), 
       array(DB2_SERVER, DB2_NAME , DB2_USER, DB2_PASSWORD, DB2_PORT), 
       array(DB3_SERVER, DB3_NAME , DB3_USER, DB3_PASSWORD, DB3_PORT), 
       array(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 для ТАБЛИЦЫ yourtable, а не проверка DATABASE db3name Так PDO выдаст ошибку:.
SQLSTATE [42S02]: База таблица или представление не найдено: 1146 Таблица «db1name.yourtable» не существует

ответ

3

У вас есть настройка как одноэлементный. Поэтому ваш следующий вызов Db::getDB возвращает исходный экземпляр. Если вы хотите кэшировать экземпляры на протяжении сценария, изменить $objInstance в массив, а затем вместо того, чтобы делать:

if (!self::$objInstance){ 

ли

$signature = $DBtype . $DBindex; 
if (!isset(self::$objInstances[$signature])) { 

Конечно, вы должны изменить линий назначения и линии возврата, но я думаю, что вы получаете идею ...

+0

Спасибо, ircmaxell.Я думаю, что это может сработать, но прямо сейчас объявляет, ссылаясь на тот код, который я только что добавил: Неустранимая ошибка: нельзя использовать объект типа PDO как массив в C: \ apache \ htdocs \ ticabo \ includes \ db.class.php on line 29 – Ticabo

+0

Что вы предлагаете? – Ticabo

+0

Как я уже сказал, вам также нужно будет изменить линии назначения (и обратную линию). Поэтому вместо выполнения 'self :: $ objInstances = new ...' и 'return self :: $ objInstances;' вам нужно выполнить 'self :: $ objInstances [$ signature] = new ...' и 'return self :: $ objInstances [$ signature]' соответственно ... – ircmaxell

2

оказывается, что функция getDB будет подключаться только один раз из-за этой линии:

if (!self::$objInstance){ 

Итак, при первом запуске он будет подключаться, но при всех последующих вызовах логика игнорируется.

Я предлагаю добавить еще одно свойство в классе, который хранит текущую DBTYPE и изменение условного к:

if (!self::$objInstance || $DBtype != self::$dbtype){ 

Вы должны установить $ DbType в каждом случае заявления выключателя.

+0

Спасибо Fosco! Позвольте мне попытаться удалить эту строку и посмотреть, как она идет :) – Ticabo

+0

Отличная идея, Fosco. Единственная проблема заключается в том, что DBtype не отличает DB :(Я работаю со многими базами данных MySQL и некоторыми MSSQL и с Oracle. Кроме того, можно добавить позже ... – Ticabo

+0

ОК, тогда какая-то комбинация dbtype и dbindex? .. у вас есть идея, правда, правильно? – Fosco

Смежные вопросы