Bootstrapping con Zend Application

Por zsamer en Agosto 30, 2009

Zend_Tool es una poderosa herramienta de Zend Framework que nos permite crear la estructura base de un proyecto Zend con todos sus directorios y componentes, como así también aprovechar un diseño estándar de proyecto y una primer clase de arranque (bootstrap) diseñada por los propios creadores del framework, ubicación para los archivos de configuración, diferenciación de entornos de ejecución (producción, desarrollo, etc), y muchos detalles más.

Crear nuestro proyecto base

Haremos un ejemplo basado en un sistema operativo como GNU/Linux, aunque esto bien se puede hacer también desde Windows a través de un .bat.

Dentro de nuestro web root, en Linux utilizando xampp: /opt/lampp/htdocs/

CODE:
  1. $ mkdir /opt/lampp/htdocs/proyecto-zf
  2. $ cd /opt/lampp/htdocs/proyecto-zf
  3. $ zf create project .
  4. Creating project at /opt/lampp/htdocs/proyecto-zf

Luego nos creará una estructura inicial para nuestro proyecto:

CODE:
  1. nuevo-proyecto-zf
  2. |-- application
  3. |   |-- Bootstrap.php
  4. |   |-- configs
  5. |   |   `-- application.ini
  6. |   |-- controllers
  7. |   |   |-- ErrorController.php
  8. |   |   `-- IndexController.php
  9. |   |-- models
  10. |   `-- views
  11. |       |-- helpers
  12. |       `-- scripts
  13. |           |-- error
  14. |           |   `-- error.phtml
  15. |           `-- index
  16. |               `-- index.phtml
  17. |-- library
  18. |-- public
  19. |   `-- index.php
  20. `-- tests
  21.     |-- application
  22.     |   `-- bootstrap.php
  23.     |-- library
  24.     |   `-- bootstrap.php
  25.     `-- phpunit.xml

De la estructura generada podemos observar lo siguiente:
Primero que todo, tenemos al directorio public. Este no solo guarda nuestro index.php quien se encarga de arrancar nuestra aplicación, sino que además contiene archivo de imágenes, hojas de estilos css, javascript etc.

Luego tenemos el directorio library, lugar donde guardamos nuestros propios componentes o librerías y las de Zend.

Después vemos que tenemos la carpeta tests, lugar donde llevaremos a cabo nuestras “pruebas unitarias” (testing). Esto puede ser usado generalmente para probar los modelos que deben contener la lógica de negocio y nuestros controladores.

Por último pero no menos importante es el directorio de la aplicación “application”. Este es considerado como el más importante, ya que es donde creamos y guardamos nuestra aplicación MVC, los controladores, modelo, vistas (script o plantillas y view helper) y archivos de configuración.
Se generó un directorio para nuestros archivos de configuración llamado configs, donde a su vez podemos ver un archivo application.ini que cuenta con los primeros parámetros que podemos definir en nuestra aplicación (entorno de producción, desarrollo, testing, si iniciar con el despliegue de mensajes de error, etc).

Nuestro archivo index.php ubicado dentro del directorio “public” quedaría más o menos con el siguiente contenido:

PHP:
  1. // Define path to application directory
  2. defined('APPLICATION_PATH')
  3.     || define('APPLICATION_PATH',
  4.               realpath(dirname(__FILE__) . '/../application'));
  5.  
  6. // Define application environment
  7. defined('APPLICATION_ENV')
  8.     || define('APPLICATION_ENV',
  9.               (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV')
  10.                                          : 'production'));
  11.  
  12. // Typically, you will also want to add your library/ directory
  13. // to the include_path, particularly if it contains your ZF installed
  14. set_include_path(implode(PATH_SEPARATOR, array(
  15.     dirname(dirname(__FILE__)) . '/library',
  16. )));
  17.  
  18. /** Zend_Application */
  19. require_once 'Zend/Application.php';
  20.  
  21. // Create application, bootstrap, and run
  22. $application = new Zend_Application(
  23.     APPLICATION_ENV,
  24.     APPLICATION_PATH . '/configs/application.ini'
  25. );
  26. $application->bootstrap()
  27.             ->run();

Podemos notar que la constante de ambiente de la aplicación "APPLICATION_ENV" referida al entorno o ambiente en que estemos, tales como de desarrollo, producción o test, esta se puede obtener directamente de la configuración del servidor web Apache, una recomendación puede ser configurarla directamente en el archivo htaccess, dentro del directorio “public”:

CODE:
  1. SetEnv APPLICATION_ENV development
  2.  
  3. RewriteEngine On
  4. RewriteCond %{REQUEST_FILENAME} -s [OR]
  5. RewriteCond %{REQUEST_FILENAME} -l [OR]
  6. RewriteCond %{REQUEST_FILENAME} -d
  7. RewriteRule ^.*$ - [NC,L]
  8. RewriteRule ^.*$ index.php [NC,L]

Adentrándonos en la Estructura de Directorio

Configs

Dentro del directorio configs, encontraremos un archivo llamado “application.ini”. Este archivo se utiliza para definir la configuración base del arranque de nuestro proyecto, el Boostrap. Veremos más adelante cómo podemos agregar recursos a la configuración del arranque, que son auto cargados por la aplicación cuando inicia. Lo fundamental es familiarizarnos con el archivo de configuración y se convertirá en uno de nuestros mejores aliados en ZF.
La configuración por defecto se coloca en “application/configs/application.ini”, y contiene algunas directrices básicas:

CODE:
  1. ; application/configs/application.ini
  2.  
  3. [production]
  4. phpSettings.display_startup_errors = 0
  5. phpSettings.display_errors = 0
  6. includePaths.library = APPLICATION_PATH "/../library"
  7. bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
  8. bootstrap.class = "Bootstrap"
  9. resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
  10.  
  11. [staging : production]
  12.  
  13. [testing : production]
  14. phpSettings.display_startup_errors = 1
  15. phpSettings.display_errors = 1
  16.  
  17. [development : production]
  18. phpSettings.display_startup_errors = 1
  19. phpSettings.display_errors = 1

Controladores

Dentro del directorio del controlador, se encuentran los archivos para cada controlador. Esto es algo que hemos visto muchas veces, así que no vamos a entrar en detalles. Al llegar a los módulos, no se olvide de anteponer el nombre de módulo, el prefijo, al nombre de clase (es decir, Admin_IndexController).

Modelos

Dentro del directorio de modelos, creamos nuestras clases modelos, un modelo contiene la lógica de negocio, pero no está vinculada a un motor de almacenamiento. Esto significa básicamente que los modelos no son sólo aquellos que extiendan de la clase Zend_Db_Table, sino que también otras fuentes de datos como un archivo plano (CVS), un XML, Web Service, SOAP, alguna fuente de dato proveniente de algún ERP etc.

Vistas

El directorio de las vistas, básicamente nuestras plantillas de presentación XHTML y las clase Helper View.

Añadiendo nuestras librerías

Por ejemplo, supongamos que hemos escrito un par de componentes para procesar archivos planos CVS y otras librerías más (como procesamiento de imágenes con GD) y las llamamos Core (nuestro propio core), entonces las almacenamos dentro del directorio library y en el sub directorio Core. Digamos que queremos añadir estas, sólo tenemos que añadir la siguiente entrada en el application.ini:

CODE:
  1. autoloaderNamespaces.core = "Core_"
  2. autoloaderNamespaces.otra  = "OtraLibreria_"
  3. autoloaderNamespaces.yotramas  = "YOtraLibreriaMas_"

Importante: desde nuestra aplicación, se espera que autoloaderNamespaces sea una matriz, razón por la cual necesitamos agregar una clave. Esto significa que podemos agregar múltiples bibliotecas personalizadas. Otro detalle a tener en cuenta es que hay que añadir un guión al final de su prefijo de la biblioteca. Tomando como ejemplo OtraLibreria, este hecho abre la puerta para las clases como OtraLibreria_NombreDeClase).

Agregando módulos

Perfecto, bueno y ¿Esto es todo? No, En realidad no… Como habrán notado, aun no tenemos un directorio de módulos. Así que vamos a cambiar eso y añadiremos nuestro primer módulo, llamado "admin".

CODE:
  1. $zf create module admin
  2. Creating the following module and artifacts:
  3. …………………..

Como pueden ver, crea un nuevo directorio llamado "modules" dentro del directorio “application”. Ahí se crea el directorio para el módulo "admin" con una estructura similar para el módulo como hemos descrito anteriormente.

Ahora vamos a crear un nuevo controlador para el módulo de modo que tengamos algo que mostrar en admin, quizás un saludo de bienvenida, esto lo hacemos manualmente como siempre lo hacemos.
Ahora, si intentamos en el navegador, ejecutar el módulo admin, vamos a obtener un mensaje de error "Message: Invalid controller specified (admin)".

Entonces, ¿qué hicimos mal? Nada en realidad. Ya que nuestra aplicación aun no está lista. Ya que hemos creado nuestro primer módulo, ahora tenemos que decirle a la configuración “application.ini” que nuestro sistema debe tener la estructura modular de directorio, por lo tanto, vamos a abrir application.ini y agregaremos las siguientes líneas al final del bloque de producción:

CODE:
  1. resources.frontController.moduleDirectory = APPLICATION_PATH "/ modules"
  2. resources.modules[] resources.modules []

Ahora estamos en condiciones de ejecutar nuestro módulo en el navegador:
http://localhost/proyecto-zf/public/admin/

El Bootstrap

La clase Bootstrap define que recursos y componentes que se deben inicializar. De forma predeterminada, el Front Controller es inicializado (Zend_Controller_Front), y configura por defecto el directorio “application/controllers/” para manejar los Controladores (Action Controllers).

PHP:
  1. class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
  2. {
  3. }

En la clase Boostraps podemos incluir recursos para que estos sean inicializados cuando arranca la aplicación. Para ello debemos agregar métodos cuyo nombre debe comenzar con el carácter underscore [ _ ] seguido de la palabra init (llamado el prefijo _init) y el nombre del recurso, comenzando este último en mayúscula y caracteres alfanuméricos.

Ejemplo: _initNombreDelRecurso():

Veamos un ejemplo de una estructura típica de una clase Boostrap con Zend_Application:

PHP:
  1. class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
  2. {
  3.     protected function _initFoo()
  4.     {
  5.         // ...
  6.     }
  7.  
  8.     protected function _initBar()
  9.     {
  10.         // ...
  11.     }
  12.  
  13.     protected function _initBaz()
  14.     {
  15.         // ...
  16.     }
  17. }

Para arrancar sólo el método _initFoo (), hacemos lo siguiente:

PHP:
  1. $bootstrap->bootstrap('foo');

Para arrancar los métodos _initFoo () e _initBar (), hacemos lo siguiente:

PHP:
  1. $bootstrap->bootstrap(array('foo', 'bar'));

Para inicializar todos los métodos de los recursos en el arranque, llamaremos a bootstrap() sin argumentos:

PHP:
  1. $bootstrap->bootstrap();

Este último es el más común y es el que observaremos en nuestro archivo de arranque index.php ubicado dentro del directorio “public”.

Veamos un ejemplo más en concreto, ahora agregaremos un recurso para inicializar el objeto vista, el cual queremos poder asignarle el HTML DocType y un valor por defecto al título HTML del sitio.
Esto puede ser implementado editando nuestra clase Bootstrap para agregar el método _initView(), veamos cómo a continuación:
?

PHP:
  1. class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
  2. {
  3.     protected function _initView()
  4.     {
  5.         // Inicializamos el objeto vista
  6.         $view = new Zend_View();
  7.         $view->doctype('XHTML1_STRICT');
  8.         $view->headTitle('My First Zend Framework Application');
  9.  
  10.         // Agregamos la vista al ViewRenderer
  11.         $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper(
  12.             'ViewRenderer'
  13.         );
  14.         $viewRenderer->setView($view);
  15.  
  16.         // Retornamos siempre el objeto recurso, en este caso la vista
  17.         // De esta manera el recurso será almacenado dentro del contenedor del Bootstrap
  18.         return $view;
  19.     }
  20. }

Este método se ejecutará automáticamente cuando se arranque la aplicación, y asegurará que nuestro objeto vista sea inicializado de acuerdo a la necesidad de nuestra aplicación.
De esta manera podríamos tener un método _initXXXX para cada uno de nuestros recursos que queramos inicializar, como por ejemplo:

Este tipo de recursos son los llamados personalizados dentro de la clase Bootstrap, por lo tanto somos nosotros quienes tenemos que implementarlo según lo que necesitemos que se inicialice en nuestra aplicación.
?
Luego, para obtener un recurso tenemos que hacerlo de las siguientes formas:

Dentro de la Clase Boostrap

PHP:
  1. $view = $this->getResource('view');

Dentro de Algún Controlador

PHP:
  1. $bootstrap = $this->getInvokeArg('bootstrap');
  2. $view = $bootstrap->getResource('view');

Para asegurarnos que el contenedor de Boostrap contiene al recursos, llamamos al método hasResource(string recurso):

PHP:
  1. if ($bootstrap->hasResource('view')) {
  2.     $view = $bootstrap->getResource('view');
  3. }

Ahora tenemos otras formas de agregar recursos y estos ya están implementados implícitamente dentro de Zend_Application (por defecto), es decir ya están disponibles y listos para usar, gracias a Zend Framework, estos son los llamados “Plugins de Recursos Disponibles”.

Para utilizarlos sólo tenemos que configurarlo (activarlo) dentro del archivo de configuración “application.ini” (lo que veremos a continuación).

Plugins de Recursos Disponibles

Resource Layout

Unos de los recursos estándar que nos provee Zend Application es el Recurso de Layout. Para activar este recurso sólo tenemos que configurar de manera adecuada nuestro archivo de configuración “application.ini” definiendo los valores para la instancia del objeto Zend Layout, nombre del layout por defecto y el path:

Entonces dentro de la etiqueta production agregamos lo siguiente:

CODE:
  1. ; Agregamos las siguientes lineas:
  2. resources.layout.layout = "layout"
  3. resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts"

Luego tenemos que crear nuestro archivo de layout dentro de la ruta especificada en la configuración “application/layouts/scripts/” el cual llamaremos layout.phtml:

PHP:
  1. <?php echo $this->doctype() ?>
  2. <html>
  3. <head>
  4.     <?php echo $this->headTitle() ?>
  5.     <?php echo $this->headLink() ?>
  6.     <?php echo $this->headStyle() ?>
  7.     <?php echo $this->headScript() ?>
  8. </head>
  9. <body>
  10.     <?php echo $this->layout()->content ?>
  11. </body>
  12. </html>

Resource View

También Zend Application nos provee de un recurso para la vista, solo tenemos que agregar unas líneas en el archivo application.ini como se muestra a continuación:

CODE:
  1. resources.view.encoding = "UTF-8"
  2. resources.view.basePath = APPLICATION_PATH "/views/scripts"

Resource Db

Tampoco se podía quedar atrás la inicialización de la conexión a las base de datos.
Zend_Application_Resource_Db inicializará un adaptador Zend_Db basado en las configuraciones asignadas en application.ini. De forma predeterminada, éste también asigna el adaptador por defecto del adaptador que debe utilizar Zend_Db_Table:

CODE:
  1. [production]
  2. resources.db.adapter = "pdo_mysql"
  3. resources.db.params.host = "localhost"
  4. resources.db.params.username = "webuser"
  5. resources.db.params.password = "XXXXXXX"
  6. resources.db.params.dbname = "test"
  7. resources.db.isDefaultTableAdapter = true

Resource Frontcontroller

Probablemente el recurso más importante y común que se carga con Zend_Application será el recurso Front Controller, que nos proporciona la capacidad de configurar Zend_Controller_Front.
Este recurso proporciona la capacidad de establecer parámetros del front controller, especificar los plugins a inicializar, y mucho más.

Una vez inicializado, el recurso asigna la propiedad $frontController del arranque a la instancia Zend_Controller_Front.

CODE:
  1. [production]
  2. resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
  3. resources.frontController.moduleControllerDirectoryName = "actions"
  4. resources.frontController.moduleDirectory = APPLICATION_PATH "/modules"
  5. resources.frontController.defaultControllerName = "site"
  6. resources.frontController.defaultAction = "home"
  7. resources.frontController.defaultModule = "static"
  8. resources.frontController.baseUrl = "/subdir"
  9. resources.frontController.plugins.foo = "My_Plugin_Foo"
  10. resources.frontController.plugins.bar = "My_Plugin_Bar"
  11. resources.frontController.env = APPLICATION_ENV

Nos adentramos en el funcionamiento de Zend Application, las funcionalidades que puede involucrar, como así también algunas de las posibilidades para ampliarlo, creando un archivo de configuración o iniciando un sistema de logger con Zend_Log, etc.

Comentarios

7 Responses to “Bootstrapping con Zend Application”

  1. Zend Application: Guía para empezar on Agosto 30th, 2009 10:50 am

    [...] bootstrapping con zend application (Español, muy bien explicado) [...]

  2. Jesús Flores on Septiembre 13th, 2009 6:19 pm

    Muy buenas,

    Hay una cosa que no comprendo en el planteamiento de la estructura de directorios en relacion a una aplicación basada en Modelos-Vistas-Controladores o por el contrario en Módulos.

    Ya que aunque efectivamente generas una carpeta para ubicar los módulos (application/modules/), siguen habiendo aún en el directorio anterior (application/) las carpetas “controllers”, “models” y “views”.

    ¿ No quedan estos directorios un poco fuera de lugar si nos basamos en módulos, o hay razones para que estos sigan estando ahí ? Si las hay, serías tan amable de explicarnoslas aunque sea brevemente ?

    Muchas gracias !!
    Y Enhorabuena por el blog. ; )

  3. zsamer on Septiembre 13th, 2009 6:49 pm

    Claro, esa es la estructura básica que se crea, sin duda podemos decirle a Zend Tool que genere la estructura modular donde cada módulo que generemos con la herramienta tendrá los directorios “controllers”, “models” y “views”.

    Además nos daremos cuenta en application.ini tendremos la linea que configura la estructura modular:
    resources.frontController.moduleDirectory = APPLICATION_PATH “/modules”

  4. YoGuuu on Septiembre 17th, 2009 8:42 pm

    Pero una vez creas esa estructura modular… ¿ Puedes automáticamente prescindir de esas tres carpetas “controllers”, “modules”, “views” ? La aplicación ya no depende de ellas ?

  5. YoGuuu on Septiembre 24th, 2009 11:06 pm

    Cuando vas a configurar application.ini para que admita modulos. El código de ejemplo está mal.

    resources.frontController.moduleDirectory = APPLICATION_PATH “/ modules”
    resources.modules[] resources.modules []

    No funciona. Si lo dejas así. Si.

    resources.frontController.moduleDirectory = APPLICATION_PATH “/modules”

    Me imagino es una errata de copia y pega.

  6. Gabriela on Octubre 31st, 2009 10:22 pm

    Hola,

    He seguido todos los pasos para crear mi proyecto y todo salió bien, pero cuando quiero crear un módulo me sale este error: “An error has ocurred. The project was not found”.

    Utilizo xampp y windows vista.

    pd: cuando creo el módulo estoy dentro de la carpeta del proyecto creado.

    Saludos

  7. Doctrine 2 ORM en Zend Framewok: parte II | Zend Framework: Estado del Arte on Noviembre 23rd, 2009 8:15 pm

    [...] Doctrine 2 con Zend Framework, para ello va ser necesario haber leido también el articulo sobre Bootstrapping con Zend Application, que será nuestra base para la [...]

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>