13

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

だから、私の2つの質問:

  1. これは DAO の正しい使い方ですか、それとも目的を誤解していますか?

  2. この程度までクエリ プロセスを抽象化することは不要ですか、それとも珍しいことですか? 物事を簡単にしようとしているように感じることがあります...

4

2 に答える 2

26

データ アクセス オブジェクトではなく、PDO (それ自体が永続化レイヤー) の上に永続化抽象化レイヤーを構築しているように見えます。DAO にはさまざまな形式がありますが、目標はビジネス ロジックを永続化メカニズムから分離することです。

  Business Logic
        |
        v
Data Access Object
        |
        v
 Persistence Layer

db_connectと を使用する DAO はselect、永続化レイヤーの後にモデル化されすぎています。汎用 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 を扱ったことはありませんが、ビジネス ロジックを PDO API に結び付けずに標準の PHP オブジェクトを生成する他の ORM ツールと似ていると思います。だから、あなたはおそらくここで大丈夫です。

たとえば、ライブラリに直接アクセスして永続性を実装している場合mysqli、結果セットとの間でデータを独自のモデル オブジェクトにコピーする必要があります。これは、ビジネス ロジックから除外する DAO の仕事です。

DAO のインターフェースを使用することで、さまざまな永続化フレームワーク (PDO、Doctrine、生の SQL など) にそれを実装できるようになりました。プロジェクトの途中でメソッドを切り替えることはほとんどありませんが、インターフェイスを使用するコストは、単体テストでモックを使用するなど、他の利点と比較してごくわずかです。

于 2012-07-01T23:27:29.153 に答える
0
  1. 必ずしも必要というわけではありませんが、それは確かに一般的な方法です。あなたがしていることよりもwaaaaayを抽象化する多くのライブラリがあります:)
于 2012-06-29T17:55:30.627 に答える