Integrando Propel con Zend Framework: Segunda Parte

Por zsamer en Junio 7, 2008

Estamos de vuelta con el articulo Integrando Propel con Zend Framework, en la Primera Parte vimos una introducción de Propel, estructuras de directorios de nuestro proyecto, finalmente como se configuran los archivos XML y se generan nuestros modelos a partir de los archivos de configuración para luego poder utilizarlos dentro de un proyecto con Zend Framework.

Hoy en esta segunda y ultima entrega veremos la integración con Zend Framework, para ello será necesario extender la clase Zend_Db_Adapter_Pdo_Mysql (utilizando mysql) y agregaremos un par de métodos y funcionalidades en la clase Core/Bootstrap de nuestro sistema cubierto en el artículos anterior Bootstrap Class.

Extendiendo la clase Zend_Db_Adapter_Abstract

En nuestro ejemplo vamos a utilizar Mysql, por lo que corresponderá extender la clase concreta Zend_Db_Adapter_Pdo_Mysql.

Primer tenemos que crear un directorio dentro de library, en nuestro articulo nombraremos al directorio Zsamer, ahí estarán todas nuestras clases que serán heredadas de las clases de Zend Framework, respetando la misma estructura de directorio (ver imagen de abajo).
quickstart\library\Zsamer:

Luego de crear la carpeta Zsamer dentro del directorio library de nuestro proyecto, tenemos que crear carpetas en cascada como muestra la imagen de arriba (quickstart\library\Zsamer\Db\Adapter\Pdo).

Nuestra clase Zsamer_Db_Adapter_Pdo_Mysql (Mysql.php) heredada de Zend_Db_Adapter_Pdo_Mysql se muestra a continuación.

quickstart\library\Zsamer\Db\Adapter\Pdo\Mysql.php:

PHP:
  1. require_once 'Zend/Db/Adapter/Pdo/Mysql.php';
  2. class Zsamer_Db_Adapter_Pdo_Mysql extends Zend_Db_Adapter_Pdo_Mysql
  3. {
  4. /**
  5. * Creates a PDO object and connects to the database.
  6. *
  7. * @return void
  8. * @throws Zend_Db_Adapter_Exception
  9. */
  10.     protected function _connect()
  11.     {
  12.         // if we already have a PDO object, no need to re-connect.
  13.         if ($this->_connection) {
  14.             return;
  15.         }
  16.         // get the dsn first, because some adapters alter the $_pdoType
  17.         $dsn = $this->_dsn();
  18.         // check for PDO extension
  19.         if (!extension_loaded('pdo')) {
  20.             /**
  21.              * @see Zend_Db_Adapter_Exception
  22.              */
  23.             require_once 'Zend/Db/Adapter/Exception.php';
  24.             throw new Zend_Db_Adapter_Exception('The PDO extension is required for this adapter but the extension is not loaded');
  25.         }
  26.         // check the PDO driver is available
  27.         if (!in_array($this->_pdoType, PDO::getAvailableDrivers())) {
  28.             /**
  29.              * @see Zend_Db_Adapter_Exception
  30.              */
  31.             require_once 'Zend/Db/Adapter/Exception.php';
  32.             throw new Zend_Db_Adapter_Exception('The ' . $this->_pdoType . ' driver is not currently installed');
  33.         }
  34.         // create PDO connection
  35.         $q = $this->_profiler->queryStart('connect', Zend_Db_Profiler::CONNECT);
  36.         require 'propel/Propel.php';
  37.         try {
  38.             $this->_connection = new PropelPDO(
  39.                 $dsn,
  40.                 $this->_config['username'],
  41.                 $this->_config['password'],
  42.                 $this->_config['driver_options']
  43.             );
  44.             $this->_profiler->queryEnd($q);
  45.             // set the PDO connection to perform case-folding on array keys, or not
  46.             $this->_connection->setAttribute(PDO::ATTR_CASE, $this->_caseFolding);
  47.             // always use exceptions.
  48.             $this->_connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  49.         } catch (PDOException $e) {
  50.             /**
  51.              * @see Zend_Db_Adapter_Exception
  52.              */
  53.             require_once 'Zend/Db/Adapter/Exception.php';
  54.             throw new Zend_Db_Adapter_Exception($e->getMessage());
  55.         }
  56.     }
  57. }

Como se darán cuenta estamos sobrescribiendo el método _connect() de la clase padre, y lo único que hace es crear la conexión utilizando el objeto/clase PropelPDO en vez de PDO, PropelPDO por supuesto que extiende a PDO.

Con esto logramos que tanto Propel como Zend_Db compartan la misma conexión a la base de datos mediante PDO.

Ahora tenemos que agregar en nuestro archivo de configuración quickstart.ini de Zend_Config un parámetro para decirle a Zend_Db que tiene que incluir el nuevo adapterNamespace "Zsamer":

quickstart\application\config\quickstart.ini

CODE:
  1. [default]
  2. ;... etc...
  3. database.adapter = PDO_MYSQL
  4. database.params.adapterNamespace = Zsamer_Db_Adapter;
  5. ;... etc...

Lo único que hicimos fue agregar una sola linea de configuración en nuestro archivo de configuración.

Por ultimo quedaría modificar el método initConnection() de la clase Bootstrap Class. y agregar un nuevo método initPropel().

PHP:
  1. /**
  2.      * Inicializacion de la base de datos information y retorna este como Zend_Db_Adapter_Abstract
  3.      * object
  4.      *
  5.      * @returns Zend_Db_Adapter_Abstract
  6.      */
  7.     public static function initConnection(Zend_Config $config)
  8.     {
  9.         Zend_Loader::loadClass('Zend_Db');
  10.         Zend_Loader::loadClass('Zend_Db_Table');
  11.         try
  12.         {
  13.             $db = Zend_Db::factory($config);
  14.             $con = $db->getConnection();
  15.             self::initPropel(null, $con);
  16.             Zend_Db_Table::setDefaultAdapter($db);
  17.         } catch (Zend_Db_Adapter_Exception $e) {
  18.             throw new Zend_Db_Adapter_Exception("Message: " . $e->getMessage() . "\n");
  19.         } catch (Zend_Exception $e) {
  20.             throw new Zend_Exception("Message: " . $e->getMessage() . "\n");
  21.         }
  22.         self::getRegistry()->set('db', $db);
  23.         return $db;
  24.     }
  25.  
  26.     public static function initPropel($name = null, PropelPDO $con)
  27.     {         
  28.         Propel::init(self::getRoot() . "/config/quickstart-conf.php");
  29.         Propel::setConnection($name, $con);
  30.     }

Explicando un poco, se crea la instancia de Zend_Db_Adapter_Abstract con Zend_Db ::factory(), luego obtenemos la conexión de tipo PDO mediante getConnection(), luego la pasamos por parametro al método initPropel para que haga un set de la conexión en Propel.

Bueno ahora falta implementar todo esto en un pequeño ejemplo dentro de un controlador.

PHP:
  1. class IndexController extends Zend_Controller_Action
  2. {
  3.     public function propelAction()
  4.     {
  5.         $project = ProjectPeer::retrieveByPK(1);
  6.         $title = $project->getTitle();
  7.         print '<pre>';
  8.         var_dump($title);
  9.        }
  10.  
  11. }

Espero que les haya servido.

En el próximo articulo vamos a ver un muy interesante tema de implementar ORM con Zend Framwork usando Zend_Db_Table y Zend_Db_Table Relationships.

Comentarios

One Response to “Integrando Propel con Zend Framework: Segunda Parte”

  1. Juan on Agosto 18th, 2008 7:54 am

    Hola,
    Enhorabuena por el articulo,
    ¿existe alguna forma de generar el schema.xml desde una base de datos Mysql ya existente? para poder hacer “ingenieria inversa” ;-)
    Gracias.

Deja tu comentario




XHTML: puedes usar estas etiquetas: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>