2010-08-19 6 views
2

S'il vous plaît, je suis très novice en PDO, plutôt novice en PHP. Je travaille actuellement sur un projet qui implique des connexions à de nombreuses bases de données: MySQL, MSSQL et Oracle. Donc j'utilise la classe ci-dessous, avec PDO, pour ma connexion. Le code de classe est ci-dessous.PDO refuse de basculer entre plusieurs bases de données!

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;  

} 

}

Et voici le vars comprennent fichier qui est requis par la classe, je un tableau parce que je sentais cette façon, de nouvelles bases de données peuvent être ajoutées facilement au fichier vars par un non-programmeur au fil du temps . Bien sûr, ici, j'ai changé les valeurs du fichier 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)    
      ); 

Maintenant, le problème est que, chaque fois que je l'ai connecté à une base de données et essayez d'exécuter mes requêtes sur un autre, PDO garde se souvenir de la vieille base de données. Mais si je cours indépendamment l'une ou l'autre question, tout va bien. Quelqu'un peut-il aider s'il vous plaît avec ceci, ou suggérer une meilleure méthode? :(

Par exemple,

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(); 
} 

Dans ce cas, PDO simplement garder le contrôle db1name de base de données pour TABLE yourtable plutôt que de vérifier BASE DE DONNÉES db3name Ainsi PDO lancera une erreur.
SQLSTATE [42S02]: base tableau ou non trouvé: 1146 Table « db1name.yourtable » n'existe pas

Répondre

3

Vous l'avez configuré en tant que singleton. Ainsi, votre prochain appel au Db::getDB renvoie l'instance d'origine. Si vous voulez mettre en cache les instances pour la durée du script, changer $objInstance à un tableau, puis au lieu de faire:

if (!self::$objInstance){ 

Do

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

Bien sûr, vous aurez besoin de changer la lignes d'affectation et la ligne de retour ainsi, mais je pense que vous avez l'idée ...

+0

Merci, ircmaxell.Je pense que cela peut fonctionner, mais maintenant il déclare, en référence à ce code que je viens d'ajouter: Erreur fatale: Impossible d'utiliser l'objet de type PDO comme tableau dans C: \ apache \ htdocs \ ticabo \ includes \ db.class.php on line 29 – Ticabo

+0

Que suggérez-vous s'il vous plaît? – Ticabo

+0

Comme je l'ai dit, vous devrez également changer les lignes d'affectation (et la ligne de retour). Donc, au lieu de faire 'self :: $ objInstances = new ...' et 'return self :: $ objInstances;', vous devrez faire 'self :: $ objInstances [$ signature] = new ...' et 'return self :: $ objInstances [$ signature]' respectivement ... – ircmaxell

2

Il semble que votre fonction GetDB ne se connecter une fois à cause de cette ligne:

if (!self::$objInstance){ 

Ainsi, la première fois que vous l'exécuterez, il se connectera, mais sur tous les appels suivants, la logique est ignorée.

Je suggère d'ajouter une autre propriété à votre classe qui stocke les DBType actuelle et l'évolution de votre condition à:

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

Vous devez définir dbtype de $ dans chaque cas de l'instruction switch.

+0

Merci Fosco! Laissez-moi essayer d'enlever cette ligne et voir comment ça se passe :) – Ticabo

+0

Excellente idée, Fosco. Le seul problème est que le DBtype ne distingue pas la DB :(Je travaille avec beaucoup de DBs MySQL et certains ceux de MSSQL et ceux d'Oracle.Plus peut aussi être ajouté plus tard ... – Ticabo

+0

ok alors une combinaison de dbtype et dbindex? .. – Fosco

Questions connexes