【发布时间】:2011-07-27 10:40:38
【问题描述】:
继续我进入更高级 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 编辑器中是相当微不足道的,但它仍然不应该是最好的方法(我现在开始学习理论而不是实践!)
所以最后,我希望我可以使用单个 switch 语句构建 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 类,但是你不能有一个有多个潜在父母的子类(可以吗?)
总结 - 我几乎可以肯定我错过了一些东西,我想做的事情应该既可能又非常简单,我只是没有想到正确的方法 - 任何人都可以给我指点吗?
【问题讨论】:
-
+1 表示出于“必须有更好的方法”提出的好问题。我会考虑一个工厂,它返回一个代理对象,然后委托给隐藏在里面的真实对象,但话说回来,我不是 PHP 程序员。
-
还要注意不同的数据库倾向于支持不同的SQL方言;这会使它们之间的切换比您预期的更难。
-
@Donal 这正是我以我现在的方式看待它的原因,所以后来的方法比如说 - selectAllRecords($table,$order) - 将能够以特定数据库的方式编写 SQL需要它来写。虽然我担心可能无法找到一种方法来消除在类之外编写任何 SQL 的需要(当涉及到复杂的查询时),但我绝对可以摆脱简单的东西。
-
我或许还应该指出,尽管我的示例很简单,但我喜欢添加许多其他功能(例如查询分析),因此这不仅仅是重新发明轮子的情况。