2

请我对 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

4

2 回答 2

3

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

if (!self::$objInstance){

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

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

于 2010-08-19T18:09:47.803 回答
2

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

if (!self::$objInstance){

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

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

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

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

于 2010-08-19T18:07:09.930 回答