# Teoría de Operación

Obtener una aplicación MVC configurada y lista para funcionar requiere de un porcentaje cada vez mayor de código que disponga de más características, tales como: Establecer la base de datos, configurar la vista y los ayudantes(helpers) de vistas, configurar los layouts, registro de plugins, registro de ayudantes de acción (action helpers), y mucho más.

Además, a menudo deseará reutilizar el mismo código para arrancar sus pruebas, un cronjob, o un servicio en linea de comandos. Si bien es posible incluir simplemente su script bootstrap, a menudo hay inicializaciones que son específicas del entorno, puede que no necesite el MVC para un cronjob, o simplemente la capa de DB para un servicio script.

`Zend_Application` pretende hacer esto más fácil y promover la reutilización mediante el encapsulamiento del bootstraping en paradigmas de OOP .

Zend_Application está dividida en tres áreas:

- `Zend_Application` : carga el entono de PHP , incluyendo include_paths y autocarga, e instancia la clase requerida de bootstrap.

- `Zend_Application_Bootstrap` : suministra interfaces para las clases bootstrap. `Zend_Application_Bootstrap_Bootstrap` ofrece funcionalidad común para la mayoría de las necesidades de bootstrap, incluyendo algoritmos de comprobación de dependencias y la capacidad de cargar recursos de bootstrap por demanda.

- `Zend_Application_Resource` provee una interfaz para recursos estandar de bootstrap que pueden ser cargados por demanda mediante una instancia bootstrap, así como implementaciones de varios recursos por defecto.

Los desarrolladores crean una clase de arranque(bootstrap) para sus aplicaciones, extendiendo `Zend_Application_Bootstrap_Bootstrap` o implementando (mínimamente) `Zend_Application_Bootstrap_Bootstrapper` . El punto de entrada (por ejemplo, public/index.php) cargará `Zend_Application` , y la instanciará pasando por:

- El entorno actual

- Opciones para bootstrapping

Las opciones de bootstrap incluyen la ruta hacia el archivo que contiene la clase bootstrap y opcionalmente:

- Cualquier include_paths extras a establecer

- Cualquier otro namespace de autocarga adicional a registrar

- Cualquier configuración de `php.ini` a inicializar

- El nombre de clase para la clase bootstrap (si no es "Bootstrap")

- Pares de recursos prefijo de ruta a usar

- Cualquier recurso a usar (por nombre de clase o nombre corto)

- Ruta adicional al archivo de configuración a cargar

- Opciones adicionales de configuración

Las opciones puden ser una array, un objeto `Zend_Config` , o la ruta a un archivo de configuración.

## Bootstrapping

La segunda área de responsabilidad de `Zend_Application` es ejecutar la solicitud del bootstrap. Los bootstraps necesitan mínimamente implementar `Zend_Application_Bootstrap_Bootstrapper` , la que define la siguiente API :

    interface Zend_Application_Bootstrap_Bootstrapper
    {
        public function __construct($application);
        public function setOptions(array $options);
        public function getApplication();
        public function getEnvironment();
        public function getClassResources();
        public function getClassResourceNames();
        public function bootstrap($resource = null);
        public function run();
    }

Esta API permite aceptar al bootstrap en el entorno y la configuración desde el objeto de la aplicación, informa la responsabilidad de los recursos para los recursos bootstraping, luego hace el bootstrap y ejecuta la aplicación.

Puede implementar esta interfaz usted mismo, extendiendo `Zend_Application_Bootstrap_BootstrapAbstract` , o usar `Zend_Application_Bootstrap_Bootstrap` .

Además de esta funcionalidad, hay muchas otras áreas de incumbencia con las cuales debe familiarizarse.

### Métodos Recursos

La implementación de `Zend_Application_Bootstrap_BootstrapAbstract` proporciona una simple convención para definir métodos de recursos de clase. Cualquier método protegido cuyo nombre comience con un prefijo _init será considerado un método de recurso.

Para arrancar un único método de recurso, utilizar el método `bootstrap()` , y pasarle el nombre del recurso. El nombre será el nombre de método menos el prefijo _init .

Para arrancar varios métodos de recursos, pasar un array de nombres. Para bootstrap de todos los métodos de recursos, no pasar nada.

Tome las siguientes clases bootstrap:

    class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
    {
        protected function _initFoo()
        {
            // ...
        }

        protected function _initBar()
        {
            // ...
        }

        protected function _initBaz()
        {
            // ...
        }
    }

Para arrancar solo el método `_initFoo()` , haga lo siguiente:

    $bootstrap->bootstrap('foo');

Para arrancar los métodos `_initFoo()` y `_initBar()` , haga lo siguiente:

    $bootstrap->bootstrap(array('foo', 'bar));

Para arrancar todos los métodos de recursos, llame a `bootstrap()` sin argumentos:

    $bootstrap->bootstrap();

### Bootstraps que usan plugins de recursos

Para hacer más re-utilizables sus bootstraps, hemos proporcionado la capacidad de impulsar sus recursos dentro de las clases de recursos de plugin. Esto le permite combinar recursos simplemente via configuración. Cubriremos el tema cómo crear recursos más adelante; en esta sección le mostraremos sólo cómo utilizarlos.

Si su bootstrap debe ser capaz de utilizar recursos de plugins, necesitará implementar una interfaz adicional, `Zend_Application_Bootstrap_ResourceBootstrapper` . Esta interfaz define una API para localizar, registrar, y cargar recursos de plugins:

    interface Zend_Application_Bootstrap_ResourceBootstrapper
    {
        public function registerPluginResource($resource, $options = null);
        public function unregisterPluginResource($resource);
        public function hasPluginResource($resource);
        public function getPluginResource($resource);
        public function getPluginResources();
        public function getPluginResourceNames();
        public function setPluginLoader(Zend_Loader_PluginLoader_Interface $loader);
        public function getPluginLoader();
    }

Básicamente los recursos de plugins ofrecen la posibilidad de crear recursos incializadores que puede ser re-utilizados entre aplicaciones. Esto le permite mantener su actual bootstrap relativamente limpio, e introducir nuevos recursos sin necesidad de tocar su propio arranque (bootstrap).

`Zend_Application_Bootstrap_BootstrapAbstract` (y `Zend_Application_Bootstrap_Bootstrap` por extensión) implementan esta interfaz, que le permite utilizar recursos de plugins.

Para utilizar recursos de plugins, debe especificarlos en las opciones que pasó al objeto aplicación y/o bootstrap. Estas opciones pueden provenir de un archivo de configuración, o ser pasadas manualmente. Las opciones deberán ser pares de clave/opción, representando con la clave el nombre del recurso. El nombre de recurso será el segmento siguiente al prefijo de clase. Por ejemplo, los recursos que vienen con Zend Framework tienen el prefijo de clase "Zend_Application_Resource_"; cualquier cosa que le siga después debe ser el nombre del recurso. Como por ejemplo,

    $application = new Zend_Application(APPLICATION_ENV, array(
        'resources' => array(
            'FrontController' => array(
                'controllerDirectory' => APPLICATION_PATH . '/controllers',
            ),
        ),
    ));

Esto indica que el recurso "Front Controller", debería ser utilizado, con las opciones especificadas.

Si usted comienza a escribir su propio recurso de plugin, o utilizar recursos de plugin de terceras partes, necesitará decirle a su bootstrap donde encontrarlos. Internamente, el bootstrap utiliza `Zend_Loader_PluginLoader` , de manera tal que sólo necesitará indicar el prefijo de la clase común como pares de path.

Supongamos por ejemplo, que usted tiene recursos de plugins personalizados en `APPLICATION_PATH/resources/` y que ellos comparten el prefijo de clase común `My_Resource` . Entonces, debería pasar esa información al objeto aplicación de la siguiente manera:

    $application = new Zend_Application(APPLICATION_ENV, array(
        'pluginPaths' => array(
            'My_Resource' => APPLICATION_PATH . '/resources/',
        ),
        'resources' => array(
            'FrontController' => array(
                'controllerDirectory' => APPLICATION_PATH . '/controllers',
            ),
        ),
    ));

Ahora usted está habilitado para utilizar los recursos de ese directorio.

Tal como los métodos de recursos, utilice el método bootstrap() para ejecutar recursos de plugins. También tal como con los métodos de recursos, puede especificar bien un único recurso de plugin, múltiples plugins (vía un array), o todos los plugins. Además, los puede combinar para ejecutar métodos de recursos.

    // Ejecute uno:
    $bootstrap->bootstrap('FrontController');

    // Ejecute varios:
    $bootstrap->bootstrap(array('FrontController', 'Foo'));

    // Ejecute todos los métodos de recursos y plugins:
    $bootstrap->bootstrap();

### Registro de Recursos

Muchos, si no todos, sus métodos de recursos o plugins inicializarán objetos y, en muchos casos, estos objetos serán necesarios en otros lugares de su aplicación. ¿Cómo se puede acceder a ellos?

`Zend_Application_Bootstrap_BootstrapAbstract` ofrece un registro local para estos objetos. Para almacenar sus objetos en ellos, simplemente debe devolverlos desde sus recursos.

Para máxima flexibilidad, este registro es mencionado internamente como un "contenedor"; el único requisito es que sea un objeto. Los recursos son luego registrados como propiedades nombrados después del nombre del recurso. Por defecto, una instancia de `Zend_Registry` es utilizada, pero también puede especificar cualquier otro objeto que desee. Los métodos `setContainer()` y `getContainer()` pueden ser utilizados para manipular el contenedor en si mismo. `getResource($resource)` puede ser utilizado para recuperar un recurso determinado del contenedor, y `hasResource($resource)` para verificar si el recurso ha sido efectivamente registrado.

Como ejemplo, considere una visión básica del recurso:

    class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
    {
        protected function _initView()
        {
            $view = new Zend_View();
            // más inicialización...

            return $view;
        }
    }

A continuación, puede comprobarlos y/o traerlos así:

    // Usando el par has/getResource():
    if ($bootstrap->hasResource('view')) {
        $view = $bootstrap->getResource('view');
    }

    // Via el contenedor:
    $container = $bootstrap->getContainer();
    if (isset($container->view)) {
        $view = $container->view;
    }

Tenga en cuenta que el registro y el contenedor no es global. Esto significa que usted necesita acceso al bootstrap a fin de recuperar recursos. `Zend_Application_Bootstrap_Bootstrap` proporciona cierta comodidad para ello: durante las ejecución de `run()` se registra a sí mismo como el "Front Controller" en el parámetro del "bootstrap", que permite buscarlo desde el router, despachador, plugins, y los contoladores de acción.

Como ejemplo, si quiere tener acceso a los recursos de la vista desde dentro de su controlador de acción, podría hacer lo siguiente:

    class FooController extends Zend_Controller_Action
    {
        public function init()
        {
            $bootstrap = $this->getInvokeArg('bootstrap');
            $view = $bootstrap->getResource('view');
            // ...
        }
    }

### Localización de las Dependencias

Además de ejecutar los métodos de recursos métodos y plugins, es necesario garantizar que estos son ejecutados una vez y solo una vez; esto es lo que se pretende con el bootstrap de una aplicación, y ejecutarlo múltiples veces puede conducir a una sobrecarga de recursos.

Al mismo tiempo, algunos recursos puede depender de otros que están en ejecución. Para resolver estas dos cuestiones, `Zend_Application_Bootstrap_BootstrapAbstract` proporciona un mecanismo simple pero eficaz para la localización de dependencias.

Como se señaló anteriormente, todos los recursos -- ya sean métodos o plugins -- son arrancados llamando a `bootstrap($resource)` , dende `$resource` es el nombre de un recurso, un array de recursos, o si se dejó vacío, indica que deberían ejecutarse todos los recursos.

Si un recurso depende de otro recurso, debe llamar a `bootstrap()` dentro de su código para garantizar que ese recurso ha sido ejecutado. Las llamadas subsiguientes a él, serán ignoradas.

En un método de recursos, esa llamada sería parecida a lo siguiente:

    class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
    {
        protected function _initRequest()
        {
            // Asegurar que el front controller es inicializado
            $this->bootstrap('FrontController');

            // Recuperar el front controller desde el registro de bootstrap
            $front = $this->getResource('FrontController');

            $request = new Zend_Controller_Request_Http();
            $request->setBaseUrl('/foo');
            $front->setRequest($request);

            // Garantizar que la solicitud es almacenada en el registro de bootstrap

            return $request;
        }
    }

## Plugins de Recursos

Como se señaló anteriormente , una buena forma de crear recursos de bootstrap re-utilizables y a traspasar mucha de su codificación a clases discretas es utilizar plugins de recursos. Si bien Zend Framework se entrega con una serie de plugins de recursos, la intención es que los desarrolladores deberían escribir los suyos para encapsular sus propias necesidades de inicialización.

Los recursos plugins solo necesitan implemetar `Zend_Application_Resource_Resource` , o más simple aún, extenderse `Zend_Application_Resource_ResourceAbstract` . La interfaz básica es simplemente esto:

    interface Zend_Application_Resource_Resource
    {
        public function __construct($options = null);
        public function setBootstrap(
            Zend_Application_Bootstrap_Bootstrapper $bootstrap
        );
        public function getBootstrap();
        public function setOptions(array $options);
        public function getOptions();
        public function init();
    }

La interfaz define simplemente que un recurso plugin debe aceptar opciones para el constructor, tiene mecanismos de establecer y recuperar opciones, mecanismos de establecer y recuperar el objeto bootstrap, y un método de inicialización.

Como ejemplo, supongamos que tiene una vista común de inicialización que utiliza en sus aplicaciones. Usted tiene un doctype común, CSS y JavaScript, y quiere se capaz de pasar desde un documento base el título via configuración. Un recurso plugin tal podría ser como este:

    class My_Resource_View extends Zend_Application_Resource_ResourceAbstract
    {
        protected $_view;

        public function init()
        {
            // Regresa la vista de manera que bootstrap la almacenará en el registro
            return $this->getView();
        }

        public function getView()
        {
            if (null === $this->_view) {
                $options = $this->getOptions();
                $title   = '';
                if (array_key_exists('title', $options)) {
                    $title = $options['title'];
                    unset($options['title']);
                }

                $view = new Zend_View($options);
                $view->doctype('XHTML1_STRICT');
                $view->headTitle($title);
                $view->headLink()->appendStylesheet('/css/site.css');
                $view->headScript()->appendfile('/js/analytics.js');

                $viewRenderer =
                    Zend_Controller_Action_HelperBroker::getStaticHelper(
                        'ViewRenderer'
                    );
                $viewRenderer->setView($view);

                $this->_view = $view;
            }
            return $this->_view;
        }
    }

Minetrtas usted haya registrado el path del prefijo para este recurso de plugin, puede usarlo en su aplicación. Mejor aún, ya que usa el cargador de plugin, usted está pasando por encima del recurso de plugin de la "View" que viene con Zend Framework, se está asegurando así que usa el suyo en lugar del original.