我有一系列课程:
abstract class Database extends PDO {}
abstract class OracleDatabase extends Database {}
abstract class MySQLDatabase extends Database {}
abstract class MSSQLDatabase extends Database {}
然后,当我想要一个数据库连接的实例时,我创建一个新类,该类扩展OracleDatabase
,MySQLDatabase
或MSSQLDatabase
,具体取决于数据库所在的位置...例如
class MyAppDatabase extends OracleDatabase {}
首先,这是一个好的设计吗?我读过最好使用接口而不是扩展抽象类,但我不确定如何在不复制代码的情况下做到这一点。
我确实意识到 PDO 的全部意义在于摆脱特定于 DB 的代码,但是对于诸如 DB 对象括号之类的事情(例如,在 Oracle 中,您使用双引号;在 MySQL 中,您使用反引号),数据时,我仍然需要不同的功能。类型检测(user_tab_columns vs INFORMATION_SCHEMA)等。
而且 - 如果我想创建一个名为的类Updater
,它允许客户端为特定表创建一组多个“更新” - 对 SET 和 WHERE 子句使用相同的字段,但使用不同的值?我认为我不能从Database
该类继承,所以我是否可以将其设为“拥有”数据库对象的独立类?
class Updater {
private $db;
private $table;
private $setFields;
private $whereFields;
private $updates;
function __construct($db, $table, $setFields, $whereFields) {
if (!($db instanceof Database)) {
if (is_scalar($db)) {
$type = gettype($db);
} else {
$type = get_class($db);
}
throw new Exception("Expected Database object; " . $type . " found.");
}
$this->db = $db;
// ensure $table is a table in the database
// ensure $setFields and $whereFields are columns in the table
$this->table = $table;
$this->setFields = $setFields;
$this->whereFields = $whereFields;
$this->updates = array();
}
function addUpdate($setValues, $whereValues) {
// ensure $setValues is an array and has the same cardinality as
// $this->setFields
// ensure $whereValues is an array and has the same cardinality as
// $this->whereFields
array_push($this->updates,
array(
'setValues'=>$setValues,
'whereValues' => $whereValues
)
);
}
function doUpdate() { // without error handling
$escTable = $this->db->bracket($table);
$setTemplate = array();
foreach ($this->setFields as $setField) {
$escField = $this->db->bracket($setField);
$colonField = makeColonField($setField); // :fieldName
$setting = "$escField = $colonField";
array_push($setTemplate, $setting);
}
$csvSetTemplate = implode(", ", $setTemplate);
$whereTemplate = array();
foreach ($this->whereFields as $whereField) {
$escField = $this->db->bracket($whereField);
$colonField = makeColonField($setField); // :fieldName
$setting = "$escField = $colonField";
array_push($whereTemplate, $setting);
}
$andedWhereTemplates = implode(" AND ", $whereTemplate);
$sql = "UPDATE $escTable SET $csvSetTemplate WHERE $andedWhereTemplates";
$sth = $this->db->prepare($sql);
foreach ($this->updates as $update) {
$setValues = $update['setValues'];
$whereValues = $update['whereValues'];
$params = array();
for ($i=0; $i<count($setValues); $i++) {
$setField = $this->setFields[$i];
$setValue = $setValues[$i];
$colonField = makeColonField($setField);
$params[$colonField] = $setValue;
}
for ($i=0; $i<count($whereValues); $i++) {
$whereField = $this->whereFields[$i];
$whereValue = $whereValues[$i];
$colonField = makeColonField($whereField);
$params[$colonField] = $whereValue;
}
$sth->execute($params);
}
}
}
这是一个好的解决方案吗?