继续我的更高级的OO之旅,我试图想出一个最好的方法来创建一个叫做database
的类,它可以愉快地使用即将被弃用的mysql_
命令,mysqli_
库,也许进一步下去,其他风格的数据库也可以。
为了简单,我希望我的调用代码看起来像这样:
$db = new database("MYSQL", $host,$user,$password,$databaseName);
$db->query("SELECT myField FROM myTable");
while ($ROW = $db->fetch_assoc($QRY)) {
echo $ROW['myField'] . "<br/>";
}
当实例化数据库对象时,这是我希望指定MYSQL, MYSQLI, MSSQL或任何我想稍后添加的部分。
我很感激我可以通过在database
的每个方法中实现switch
块来实现我想要的:
class database() {
function __construct($type,$host,$user,$password,$databaseName) {
$this->dbType = $type;
switch ($type) {
case "mysql":
mysql_dao::connect($host,$user,$password,$databaseName);
break;
case "mysqli":
mysqli_dao::connect($host,$user,$password,$databaseName);
break;
case "mssql":
mssql_dao::connect($host,$user,$password,$databaseName);
break;
//other cases
}
}
function query($SQL) {
switch ($this->dbType) {
case "mysql": mysql_dao::query($SQL); break;
case "mysqli": mysqli_dao::query($SQL); break;
case "mssql": mssql_dao::query($SQL); break;
}
}
function fetch_assoc($SQL) {
switch ($this->dbType) {
case "mysql": mysql_dao::fetch_assoc($SQL); break;
case "mysqli": mysqli_dao::fetch_assoc($SQL); break;
case "mssql": mssql_dao::fetch_assoc($SQL); break;
}
}
//other methods....
}
…但这看起来非常混乱。每次调用database
的方法时,代码都会检查它是什么类型,并从不同的对象调用该方法。
所以我的下一个解决方案是简单地忽略database
,只是使用调用代码,看起来像这样:
$db = new mysql_dao($host,$user,$password,$databaseName);
$db->query("SELECT myField FROM myTable");
while ($ROW = $db->fetch_assoc($QRY)) {
echo $ROW['myField'] . "<br/>";
}
…根据数据库类型调用数据库访问对象,但我也不喜欢这样,如果我想把整个项目从mysql转移到mysqli,我就得找出所有这些对象引用并修改它们。虽然这在现代PHP编辑器中是相当微不足道的,但它仍然感觉不应该是最好的方法(现在我开始从实际出发,而不是从理论出发!)
所以最后,我希望我可以用一个开关语句构建database
类:
class database {
function __construct($type,$host,$user,$pass,$db) {
switch ($type) {
default:
case "MYSQL":
return new mysql_dao($host,$user,$pass,$db);
break;
case "MYSQLI":
return new mysqli_dao($host,$user,$pass,$db);
break;
case "MSSQL":
return new mssql_dao($host,$user,$pass,$db);
break;
}
}
}
…然后实现一个接口所有其他的方法都在类中用于各个数据库类型。不幸的是,这也不起作用,因为即使database
的构造函数返回另一个对象的实例,我也不能调用database->query
,因为该方法不存在于数据库对象中。
据我所知,用mysql_dao
/mysqli_dao
等类扩展database
也是不对的,因为你必须调用扩展类来使用它的方法,我想调用父类,但使用子类的方法。所以这表明database
应该扩展dao
类,但你不能有一个子类与多个潜在的父母(你可以吗?)
总结-我几乎肯定我错过了一些东西,我想做的应该是既可能又相当直接的,我只是没有想到正确的方法-谁能给我一个指针?
尽管您正在做的是重新发明轮子(看看PDO),但通常情况下,对于这种情况,您可能希望使用类似工厂模式的东西。
在基本伪代码中:
$db = Database::create('mysql', $host, ...); // gets a MySQLDatabase object
$db = Database::create('mysqli', $host, ...); // gets a MySQLiDatabase object
为什么不直接使用PDO?它提供了与一系列数据库连接的统一方式(它执行的实际查询必须考虑到目标数据库,但无论连接到哪种数据库,API都是相同的)。
在这种情况下,我会:
- 定义一些
DAOInterface
,方法如connect
,query
,fecthAll
,…- 所有连接到数据库的类都必须实现该接口
- 这意味着你的
mysql_dao
,mysqli_dao
,…将实现该接口
那么,当使用这些类时,主要的优点是:
- 您稍后将实例化,作为
$db
变量,mysql_dao
或mysqli_dao
,但总是得到一个实现DAOInterface
的对象 - 这意味着你将确保你可以调用所有这些方法,在你的
$db
对象
在那之后,只有一个地方你必须在mysql_dao
和mysqli_dao
之间进行选择:当你实例化这两个中的一个时,将结果赋值给$db
。
那么,既然你知道$db
是一个实现DAOInterface
的对象,你就知道你总是能够在那个对象上调用相同的方法。
为了使功能发挥作用,您需要传递和返回参数作为引用,如下面的示例所示:
public function &Query($sql){
$var = mysql_query($sql, $this->connection);
return $var;
}
public function Fetch(&$cur){
return mysql_fetch_array($cur);
}
"&"表示变量的引用,而不仅仅是更多文档的副本:http://www.php.net/manual/en/language.references.pass.php
你正在努力做的事情很有效。我创建了一个MySQL数据库接口,但我相信您会找到一种方法来为不同类型的数据库创建对象。