PDO拒绝在多个数据库之间切换!

时间:2010-08-19 17:59:42

标签: php mysql oracle pdo mysql-error-1146

请问我是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;      

}

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包含文件,我使用了数组cos,我觉得这样,随着时间的推移,非程序员可以轻松地将新数据库添加到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就会记住旧数据库。但如果我独立运行任何查询,一切都很好。有人可以帮忙解决这个问题,还是建议一个更好的方法? :(

E.g。

}

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将继续检查用于TABLE yourtable的DATABASE db1name,而不是检查DATABASE db3name。所以PDO会抛出一个错误:
SQLSTATE [42S02]:未找到基表或视图:1146表'db1name.yourtable'不存在

2 个答案:

答案 0 :(得分:3)

您将其设置为单身人士。因此,您对Db::getDB的下一次调用将返回原始实例。如果要在脚本持续时间内缓存实例,请将$objInstance更改为数组,然后执行以下操作:

if (!self::$objInstance){

待办事项

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

当然你也需要改变作业线和回归线,但我觉得你明白了......

答案 1 :(得分:2)

由于以下行,您的getDB函数似乎只会连接一次:

if (!self::$objInstance){

因此,当您第一次执行它时,它将连接,但在所有后续调用中,逻辑将被忽略。

我建议在您的类中添加另一个属性,用于存储当前的DBType并将条件更改为:

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

您必须在switch语句的每个case中设置$ dbtype。