PHP 数据访问对象

标签 php design-patterns data-access-layer

我试图弄清楚我是否正确地使用了 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

那么,我的两个问题:

  1. 这是对 DAO 的正确使用,还是我误解了它的用途?

  2. 将查询过程抽象到这种程度是不必要的,甚至是不常见的吗?有时我觉得我试图让事情变得太简单......

最佳答案

它看起来更像是在 PDO(它本身就是一个持久层)之上构建一个持久性抽象层,而不是 data access object。 .虽然 DAO 可以采用多种形式,但目标是将您的业务逻辑与持久性机制分开。

  Business Logic
        |
        v
Data Access Object
        |
        v
 Persistence Layer

具有 db_connectselect 的 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/

相关文章:

sql - 这些数据库设计风格(或反模式)有名字吗?

node.js - MongoDB 的 DAL

c# - 可插拔数据库层的建议

php - 如何通过插件更新推送 WordPress 帖子内容?

php - 在 PHP 页面中传递变量

php - 如何在PHP中实现双向链表?

javascript - 两个按钮一种形式

sql-server - 识别存储空间的分配算法

c# - 在解决方案的类库项目中获取连接字符串

c# - 这是对泛型和 C# 的动态数据类型的适当使用吗?