【问题标题】:PDO refuses to switch between multiple Databases!PDO 拒绝在多个数据库之间切换!
【发布时间】:2010-08-19 17:59:41
【问题描述】:

请我对 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 包含文件,我使用了一个数组,因为我觉得这样,随着时间的推移,非程序员可以轻松地将新数据库添加到 vars 文件中。当然,在这里,我已经更改了 var 文件的值。

定义('DB_SERVER','localhost'); 定义('DB_NAME','db1name'); 定义('DB_USER','root'); 定义('DB_PASSWORD','rootpass'); 定义('DB_PORT',''); 定义('DB2_SERVER', 'xxx.xxx.xx.xxx'); 定义('DB2_NAME','db2name'); 定义('DB2_USER', 'root2'); 定义('DB2_PASSWORD', 'rootpass2'); 定义('DB2_PORT', ''); 定义('DB3_SERVER', 'xx.xxx.xxx.xxx'); 定义('DB3_NAME',db3name'); 定义('DB3_USER', 'root3'); 定义('DB3_PASSWORD', 'rootpass3'); 定义('DB3_PORT', ''); 定义('DB4_SERVER', 'xxx.xx.xxx.xx'); 定义('DB4_NAME','oracledb'); 定义('DB4_USER', 'root4'); 定义('DB4_PASSWORD','rootpass4'); 定义('DB4_PORT','1521'); $dbvars = 数组(数组(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]: Base table or view not found: 1146 Table 'db1name.yourtable' doesn't exist

【问题讨论】:

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


    【解决方案1】:

    您已将其设置为单例。因此,您对Db::getDB 的下一次调用将返回原始实例。如果要在脚本执行期间缓存实例,请将 $objInstance 更改为数组,然后不要这样做:

    if (!self::$objInstance){
    

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

    当然,您还需要更改分配线和返回线,但我想您明白了...

    【讨论】:

    • 谢谢,ircmaxell。我认为这可能有效,但现在它声明,引用我刚刚添加的代码:致命错误:无法在第 29 行的 C:\apache\htdocs\ticabo\includes\db.class.php 中使用 PDO 类型的对象作为数组
    • 正如我所说,您还需要更改分配行(以及返回行)。因此,您需要分别执行self::$objInstances[$signature] = new...return self::$objInstances[$signature],而不是执行self::$objInstances = new...return self::$objInstances;...
    • 耶!!!它像魔术一样工作!!!谢谢!!!!你就是那个男人!现在我真的需要学习OOP。 :-)
    • 嗯,这不是真正的 OOP。那只是动态地将东西存储在一个数组中......但很高兴我能提供帮助......
    【解决方案2】:

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

    if (!self::$objInstance){
    

    所以第一次执行时,它会连接,但在所有后续调用中,逻辑都会被忽略。

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

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

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

    【讨论】:

    • 感谢福斯科!让我试着删除那条线,看看它是怎么回事:)
    • 好主意,福斯科。唯一的问题是 DBtype 不能区分 DB :( 我正在使用许多 MySQL 数据库和一些 MSSQL 数据库和一个 Oracle 数据库。以后可能还会添加更多...
    • 好的,那么 dbtype 和 dbindex 的某种组合?...不过,你明白了,对吧?
    • 是的,福斯科!我明白了。我非常感谢您的帮助。 Ircmaxwell 给出了类似的建议,结合了 dbtype 和 dbindex :) 唯一的问题是我还不能完全围绕 PDO 对象/数组的东西(我现在对 OOP 知之甚少)。再次感谢。
    猜你喜欢
    • 2012-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-22
    • 2016-09-07
    • 1970-01-01
    相关资源
    最近更新 更多