2012-06-29 47 views
12

我想弄清楚,如果我正確地使用DAO模式,更具體,抽象的DB持久性應該如何通過它獲取到我的映射器類的時間。我使用PDO作爲數據訪問抽象對象,但有時我想知道我是否試圖抽象查詢太多。PHP數據訪問對象

我剛剛列入我如何提取選擇查詢,但我寫的所有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. 是抽象的查詢過程,這種程度的不必要的,甚至是罕見的?有時候我覺得我試圖讓事情太容易了......

回答

20

它看起來更像你在PDO(這本身是一個持久層)之上構建一個持久抽象層,而不是data access object 。儘管DAO可以採用多種形式,但目標是將業務邏輯與持久性機制分開。

Business Logic 
     | 
     v 
Data Access Object 
     | 
     v 
Persistence Layer 

甲DAO與db_connectselect在持久層之後過於緊密建模。通用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對象,而無需將業務邏輯綁定到PDO API。所以你可能在這裏很好。

如果您通過直接訪問mysqli庫來實現持久性,例如,您希望將結果集中的數據複製到您自己的模型對象中。這是DAO的工作,使其脫離業務邏輯。

通過使用DAO接口,您現在可以爲不同的持久性框架實現它:PDO,Doctrine,原始SQL,無論如何。雖然您不可能在項目中間切換方法,但與其他好處相比,使用界面的成本可以忽略不計,例如,在單元測試中使用模擬。

+0

所以在域模型每個域對象可以/應該有一個CRUD操作,那麼一個相關的DAO對象? – jerry

+0

@saddog - 每個根級對象,是的。例如,'Order'及其'LineItem'子列表可能會通過'OrderDao'存儲在一起。不幸的是,你很少*完全*將業務邏輯與持久化域模型對象分開。 –

+0

好的,這實際上帶來了更多的問題,然後我會接受並給你賞金。你提到了LineItem子項,我想確保在應用程序中正確處理這些子項。這些孩子會映射到數據庫中的表(一個LineItem表),並由Dao合併到Order域對象中嗎?即DaoUser中的createObject方法是將這兩個對象放在一起的方法嗎? – jerry

0
  1. 這不一定是必要的,但它肯定是常見的做法。有許多庫,抽象waaaaay進一步比你在做什麼:)