2013-04-23

Gestión de datos en PHP

Os voy a exponer como hago yo la gestión de datos en PHP, apoyándome en el modelado con clases y el patrón DAO (Data Access Object).

Los Objetos de Acceso a Datos son un patrón de diseño J2EE considerados una buena práctica. Un DAO permite abstraer y encapsular todos los accesos a la fuente de datos (normalmente una base de datos, como MySQL). EL DAO gestiona la conexión con la fuente de datos para obtener y almacenar datos, implementando los mecanismos de acceso requeridos.  El DAO oculta los detalles de implementación del origen de datos a sus clientes. Debido a que la interfaz expuesta por el DAO a los clientes no cambia cuando cambia la implementación del origen de datos suybacente, este modelo permite al DAO adaptarse a diferentes esquemas de almacenamiento sin afectar a sus clientes o componentes de negocio.

El siguiente diagrama de clases representa las relaciones del patrón DAO:
Y en el siguiente diagrama de secuencia se representa la interacción entre los distintos participantes del patrón:
El BusinessObject es el cliente que requiere el acceso a la fuente de datos para obtener y almacenar datos. El DataAccessObject es en quien delega el BusinessObject para hacer estas operaciones. El DataSource representa una implementación de una fuente de datos (como un RDBMS). El TransferObject representa un soporte temporal de datos. El DataAccessObject puede utilizar un TransferObject para devolver datos al cliente o recibir los datos del cliente en un TransferObject para actualizar los datos del DataSource.


Esta es la manera en que yo aplico el patrón DAO en PHP para gestionar los datos en las aplicaciones de forma uniforme, encapsulada y sencilla:

Voy a utilizar como ejemplo la siguiente tabla FABRICANTES:
(Ver: Modelo de datos)
CREATE TABLE fabricantes (
  id smallint(5) NOT NULL AUTO_INCREMENT,
  codigo varchar(10) NOT NULL,
  denominacion_social varchar(100) NOT NULL,
  activo tinyint(1) NOT NULL DEFAULT '1',
  PRIMARY KEY (id)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
  1. Por cada tabla creamos dos clases PHP:
    (Para no tener que hacer includes de las clasese en los scripts, ver: )
    • class.fabricante.php, que será el TransferObject, con variables para cada campo de la tabla:
    <?php
    class Fabricante extends Desactivable {
     
    public $id;
    public $codigo;
    public $denominacion_social;
    
    }
    ?>
    
    • class.fabricantes.php, que será el DataAccessObject
    <?php
    define('FABRICANTES_FIELDS_SIN_ID', 'codigo, denominacion_social');
    define('FABRICANTES_FIELDS', 'id, ' . FABRICANTES_FIELDS_SIN_ID);
    define('FABRICANTES_SELECT', 'SELECT ' . FABRICANTES_FIELDS . ' FROM fabricantes WHERE 1 = 1');
    define('FABRICANTES_ORDER', ' ORDER BY denominacion_social');
    define('FABRICANTES_INSERT', 'INSERT INTO fabricantes (' . FABRICANTES_FIELDS_SIN_ID . ') VALUES (%s, %s)');
    define('FABRICANTES_UPDATE', 'UPDATE fabricantes SET codigo = %s, denominacion_social = %s WHERE id = %s');
    define('FABRICANTES_DELETE', 'UPDATE fabricantes SET activo = 0 WHERE activo = 1');
    
    class Fabricantes {
    
     function getFabricante($id, $activo = true) {
      $sql = sprintf(FABRICANTES_SELECT . ($activo? ' AND activo = 1' : '') . ' AND id = %s',
        param($id));
      $result = mysql_query($sql) or trigger_error(mysql_error());
      if ($obj = mysql_fetch_object($result, 'Fabricante')) {
       return $obj;
      }
    
      return false;
     }
    
     function getFabricantes($fab = null, $orden = null, $ordenado = null) {
      $sql = FABRICANTES_SELECT . ' AND activo = 1';
      if (isset($fab)) {
       if ($fab->codigo != '') {
        $sql .= sprintf(' AND codigo = %s',
          param($fab->codigo));
       }
      }
      if (isset($orden)) {
       $sql .= ' ORDER BY ' . $orden . '';
       if (isset($ordenado)) {
        $sql .= ' ' . $ordenado;
       }
      } else {
       $sql .= FABRICANTES_ORDER;
      }
      $result = mysql_query($sql) or trigger_error(mysql_error());
      while ($obj = mysql_fetch_object($result, 'Fabricante')) {
       $objs[] = $obj;
      }
     
      if (isset($objs)) {
       return $objs;
      }
      return false;
     } 
    
     function setFabricante($fab) {
      if ($fab->id == null) {
       $sql = sprintf(FABRICANTES_INSERT,
         param($fab->codigo), param($fab->denominacion_social));
      } else {
       $sql = sprintf(FABRICANTES_UPDATE,
         param($fab->codigo), param($fab->denominacion_social), $fab->id);
      }
      mysql_query($sql) or trigger_error(mysql_error());
      if (mysql_affected_rows() === 1) {
       if ($fab->id == null) {
        $fab->id = mysql_insert_id();
       }
       return true;
      }
     
      return false;
     } 
    
     function remFabricantes($ids) {
      $sql = sprintf(FABRICANTES_DELETE . ' AND id IN (%s)', $ids);
      mysql_query($sql) or trigger_error(mysql_error());
      return mysql_affected_rows();
     } 
     
    }
    ?>
    
  2. Uso desde un cliente o BusinessObject:
    (Ver Autocarga de clases en PHP)
    <?php
    $fabMgr = new Fabricantes();
    if ($_POST['id'] != '') {
     $fab = $fabMgr->getFabricante($_POST['id']);
    } else {
     $fab = new Fabricante();
    }
    
    $fab->codigo = $_POST['codigo'];
    $fab->denominacion_social = $_POST['denominacion_social'];
     
    if ($fabMgr->setFabricante($fab)) { 
     $cambios = $fab->id;
    } else {
     $errores = 'Fabricante no guardado';
    }
    ?>
    

No hay comentarios:

Publicar un comentario