2012-06-29 12 views
12

Sto cercando di capire se sto usando il pattern DAO correttamente e, più specificamente, come dovrebbe essere la persistenza db astratta nel momento in cui arriva alle mie classi di mapper. Sto usando PDO come oggetto di astrazione di accesso ai dati, ma a volte mi chiedo se sto cercando di astrarre troppo le query.Oggetto accesso dati PHP

Ho appena incluso come sto estraendo le query selezionate, ma ho scritto i metodi per tutte le operazioni 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 

Quindi, le mie due domande:

  1. E 'questo il corretto utilizzo di un DAO, o sto interpretando male il suo scopo?

  2. L'astrazione del processo di ricerca in questo grado non è necessaria o addirittura rara? A volte mi sento come se stessi cercando di fare le cose troppo facili ...

risposta

20

Sembra più si sta costruendo uno strato di persistenza di astrazione in cima alla DOP (che è essa stessa uno strato di persistenza), piuttosto che un data access object . Mentre ci sono molte forme che un DAO può assumere, l'obiettivo è separare la logica aziendale dal meccanismo di persistenza.

Business Logic 
     | 
     v 
Data Access Object 
     | 
     v 
Persistence Layer 

Un DAO con db_connect e select è troppo strettamente modellato dopo che lo strato di persistenza. La forma più semplice di un DAO generico consiste nel fornire le operazioni CRUD di base a livello di oggetto senza esporre le parti interne del meccanismo di persistenza.

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); 
} 

Se gli oggetti di business sono gli oggetti del modello sottostanti DOP, è possibile restituirli dal DAO. Essere consapevoli del fatto che, a seconda del meccanismo di persistenza sottostante scelto, questo potrebbe non essere l'ideale. Non ho lavorato con PDO ma presumo che sia simile ad altri strumenti ORM che producono oggetti PHP standard senza legare la logica aziendale all'API PDO. Quindi stai probabilmente bene qui.

Se si stava implementando la persistenza accedendo direttamente alla libreria mysqli, ad esempio, si desidera copiare i dati in/dai set di risultati nei propri oggetti modello. Questo è il compito del DAO di tenerlo fuori dalla logica del business.

Utilizzando un'interfaccia per DAO ora è possibile implementarlo per diversi framework di persistenza: PDO, Doctrine, SQL raw, qualsiasi cosa. Anche se è improbabile che tu cambi i metodi a metà progetto, il costo di utilizzo di un'interfaccia è trascurabile rispetto ai suoi altri vantaggi, ad es. usando una simulazione nelle prove di unità.

+0

Quindi, ogni oggetto dominio nel modello di dominio potrebbe/dovrebbe avere un oggetto Dao correlato per le operazioni CRUD, quindi? – jerry

+0

@saddog - Ogni oggetto di livello root, sì. Ad esempio, un 'Ordine' e il suo elenco di bambini' LineItem' verrebbero probabilmente archiviati insieme attraverso 'OrderDao'. Sfortunatamente, raramente è possibile * completamente * isolare la logica aziendale dal modo in cui si mantengono gli oggetti del modello di dominio. –

+0

Ok, questo fa sorgere ancora una domanda, e poi accetterò e ti darò la taglia. Parli dei bambini di LineItem e voglio assicurarmi che li gestirò correttamente nella mia applicazione.Questi bambini sarebbero mappati alle tabelle nel db (una tabella LineItem) e sarebbero semplicemente consolidati nell'oggetto Dominio dell'ordine dal Dao? vale a dire un metodo createObject nel DaoUser sarebbe quello per riunire questi due oggetti? – jerry

0
  1. Non è necessariamente necessario, ma è certamente una pratica comune. Ci sono molte librerie che astratto waaaaay oltre quello che stai facendo :)