2012-06-29 28 views
12

Estoy tratando de averiguar si estoy usando el patrón DAO correctamente y, más específicamente, qué tan abstracto debe ser la persistencia de db para cuando llegue a mis clases de asignador. Estoy utilizando PDO como el objeto de abstracción de acceso a datos, pero a veces me pregunto si estoy tratando de abstraer demasiado las consultas.Objeto de acceso a datos de PHP

Acabo de incluir cómo estoy abstrayendo las consultas de selección, pero he escrito métodos para todas las operaciones 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 

Por lo tanto, mis dos preguntas:

  1. Es este el uso correcto de un DAO, o estoy mal interpretando su propósito?

  2. ¿Es innecesario o poco común que se resuma el proceso de consulta a este grado? A veces me siento como si estuviera tratando de hacer las cosas demasiado fáciles ...

Respuesta

20

Se ve más como está la construcción de una capa de abstracción de persistencia en la parte superior de la DOP (que es en sí misma una capa de persistencia) en lugar de un data access object . Si bien hay muchas formas que un DAO puede tomar, el objetivo es separar su lógica comercial del mecanismo de persistencia.

Business Logic 
     | 
     v 
Data Access Object 
     | 
     v 
Persistence Layer 

A DAO con db_connect y select es demasiado de cerca el modelo de la capa de persistencia. La forma más simple de un DAO genérico es proporcionar las operaciones CRUD básicas a nivel de objeto sin exponer las partes internas del mecanismo de persistencia.

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

Si sus objetos comerciales son los objetos subyacentes del modelo PDO, puede devolverlos desde el DAO. Tenga en cuenta que dependiendo del mecanismo de persistencia subyacente que elija, esto puede no ser ideal. No he trabajado con PDO, pero supongo que es similar a otras herramientas de ORM que producen objetos PHP estándar sin vincular la lógica de negocios a la API de PDO. Entonces probablemente estés bien aquí.

Si estaba implementando la persistencia accediendo directamente a la biblioteca mysqli, por ejemplo, le gustaría copiar datos a/desde los conjuntos de resultados en sus propios objetos de modelo. Este es el trabajo del DAO para mantenerlo fuera de la lógica comercial.

Al utilizar una interfaz para DAO, ahora puede implementarla para diferentes marcos de persistencia: PDO, Doctrine, SQL sin procesar, lo que sea. Si bien es poco probable que cambie los métodos a mitad de proyecto, el costo de usar una interfaz es insignificante en comparación con sus otros beneficios, p. usando un simulacro en pruebas unitarias.

+0

Entonces, ¿cada objeto de dominio en el modelo de dominio podría/debería tener un objeto Dao relacionado para las operaciones CRUD? – jerry

+0

@saddog - Cada objeto de nivel raíz, sí. Por ejemplo, un 'Order' y su lista de hijos' LineItem' probablemente se almacenarían juntos a través de 'OrderDao'. Desafortunadamente, rara vez puede * completamente * aislar la lógica empresarial de cómo persiste los objetos del modelo de dominio. –

+0

Bien, eso en realidad trae a colación una pregunta más, y luego aceptaré y te daré la recompensa. Usted menciona hijos de LineItem y quiero asegurarme de que los manejaría correctamente en mi aplicación.¿Estarían estos niños asignados a las tablas en el db (una tabla de LineItem) y simplemente serían consolidados en el objeto de dominio Order por el Dao? es decir, ¿un método createObject en DaoUser sería el que uniría estos dos objetos? – jerry

0
  1. No es necesariamente necesario, pero es sin duda una práctica común. Hay muchas bibliotecas que abstraen muuuuchas más allá de lo que está haciendo :)