PHP数据访问对象

时间:2012-06-29 17:34:48

标签: php design-patterns data-access-layer

我正在试图弄清楚我是否正确使用DAO模式,更具体地说,当它到达我的mapper类时,抽象数据库持久性应该是多少。我正在使用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. 将查询过程抽象到这个程度是不必要的,甚至是不常见的?有时我觉得我想让事情变得太容易......

2 个答案:

答案 0 :(得分:22)

看起来你更像是在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,但是假设它与生成标准PHP对象的其他ORM工具类似,而不会将业务逻辑与PDO API联系起来。所以你在这里可能还可以。

例如,如果您通过直接访问mysqli库来实现持久性,则需要将数据复制到结果集中或从结果集中复制数据到您自己的模型对象中。这是DAO的工作,使其远离业务逻辑。

通过使用DAO的接口,您现在可以为不同的持久性框架实现它:PDO,Doctrine,原始SQL等等。虽然您不太可能在项目中间切换方法,但与其他好处相比,使用接口的成本可以忽略不计,例如:在单元测试中使用模拟。

答案 1 :(得分:0)

  1. 这不一定是必要的,但这当然是常见的做法。有许多图书馆比你正在做的更抽象地抽象了...