我试图弄清楚我是否正确地使用了 DAO 模式,更具体地说,当它到达我的映射器类时,抽象数据库持久性应该如何。我正在使用 PDO 作为数据访问抽象对象,但有时我想知道我是否试图过多地抽象查询。
我刚刚介绍了如何抽象选择查询,但我已经为所有 CRUD 操作编写了方法。
class DaoPDO {
function __construct() {
// connection settings
$this->db_host = '';
$this->db_user = '';
$this->db_pass = '';
$this->db_name = '';
}
function __destruct() {
// close connections when the object is destroyed
$this->dbh = null;
}
function db_connect() {
try {
/**
* connects to the database -
* the last line makes a persistent connection, which
* caches the connection instead of closing it
*/
$dbh = new PDO("mysql:host=$this->db_host;dbname=$this->db_name",
$this->db_user, $this->db_pass,
array(PDO::ATTR_PERSISTENT => true));
return $dbh;
} catch (PDOException $e) {
// eventually write this to a file
print "Error!: " . $e->getMessage() . "<br/>";
die();
}
} // end db_connect()'
function select($table, array $columns, array $where = array(1=>1), $select_multiple = false) {
// connect to db
$dbh = $this->db_connect();
$where_columns = array();
$where_values = array();
foreach($where as $col => $val) {
$col = "$col = ?";
array_push($where_columns, $col);
array_push($where_values, $val);
}
// comma separated list
$columns = implode(",", $columns);
// does not currently support 'OR' arguments
$where_columns = implode(' AND ', $where_columns);
$stmt = $dbh->prepare("SELECT $columns
FROM $table
WHERE $where_columns");
$stmt->execute($where_values);
if (!$select_multiple) {
$result = $stmt->fetch(PDO::FETCH_OBJ);
return $result;
} else {
$results = array();
while ($row = $stmt->fetch(PDO::FETCH_OBJ)) {
array_push($results, $row);
}
return $results;
}
} // end select()
} // end class
那么,我的两个问题:
这是对 DAO 的正确使用,还是我误解了它的用途?
将查询过程抽象到这种程度是不必要的,甚至是不常见的吗?有时我觉得我试图让事情变得太简单......
最佳答案
它看起来更像是在 PDO(它本身就是一个持久层)之上构建一个持久性抽象层,而不是 data access object。 .虽然 DAO 可以采用多种形式,但目标是将您的业务逻辑与持久性机制分开。
Business Logic
|
v
Data Access Object
|
v
Persistence Layer
具有 db_connect
和 select
的 DAO 过于接近于持久层建模。通用 DAO 的最简单形式是在对象级别提供基本的 CRUD 操作,而不暴露持久性机制的内部结构。
interface UserDao
{
/**
* Store the new user and assign a unique auto-generated ID.
*/
function create($user);
/**
* Return the user with the given auto-generated ID.
*/
function findById($id);
/**
* Return the user with the given login ID.
*/
function findByLogin($login);
/**
* Update the user's fields.
*/
function update($user);
/**
* Delete the user from the database.
*/
function delete($user);
}
如果您的业务对象是底层 PDO 模型对象,您可以从 DAO 返回它们。请注意,根据您选择的底层持久性机制,这可能并不理想。我没有使用过 PDO,但假设它类似于其他 ORM 工具,这些工具可以生成标准的 PHP 对象,而无需将业务逻辑绑定(bind)到 PDO API。所以你在这里可能没问题。
如果您通过直接访问 mysqli
库来实现持久性,例如,您可能希望将数据复制到结果集中/从结果集中复制到您自己的模型对象中。这是 DAO 的工作,将其排除在业务逻辑之外。
通过使用 DAO 的接口(interface),您现在可以为不同的持久性框架实现它:PDO、Doctrine、原始 SQL 等等。虽然您不太可能在项目中期切换方法,但与其他好处相比,使用接口(interface)的成本可以忽略不计,例如在单元测试中使用模拟。
关于PHP 数据访问对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11266388/