# ViewRenderer

## Introducción

El ayudante ViewRenderer está diseñado para satisfacer los siguientes objetivos:

- Eliminar la necesidad de instanciar objetos de vista dentro de los controladores; los objetos de vista quedarán registrados automáticamente con el contralor.

- Establece automáticamente el script de vista, el ayudante, y los paths de los filtros basados en el módulo actual. Asocia automáticamente el nombre del módulo actual como un prefijo de clase para las clases ayudante y filtro.

- Crea un objeto de vista, disponible globalmente para todos los controladores y acciones despachados.

- Permite al desarrollador establecer por defecto las opciones de renderizado para todos los controladores.

- Agrega la capacidad para renderizar automáticamente los scripts de vista sin ninguna intervención.

- Permite al desarrollador crear sus propias especificaciones para el path base de vistas y para el path de los scripts de vista.

Si realiza un `_forward()` , redirecciona, o `render()` manualmente, el autorendering no se llevará a cabo, como está realizando cualquiera de estas acciones le está diciendo al ViewRenderer que usted está determinando su propia salida.

El ViewRenderer está habilitado por defecto. Puede desactivarlo vía parámetro del front controller noViewRenderer (`$front->setParam('noViewRenderer',true)`) o eliminando al ayudante del stack de ayudantes ( `Zend_Controller_Action_HelperBroker::removeHelper('viewRenderer')` ).

Si desea modificar los settings del ViewRenderer antes de despachar el front controller, puede hacerlo en una de las dos maneras:

- Instanciar y registrar su propio objeto ViewRenderer y pasarlo al ayudante:

      $viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer();
      $viewRenderer->setView($view)
                   ->setViewSuffix('php');
      Zend_Controller_Action_HelperBroker::addHelper($viewRenderer);

- Inicializar y/o recuperar un objeto ViewRenderer por demanda via el ayudante:

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

## API

En su uso más básico, simplemente instancie a ViewRenderer y páselo al ayudante de acciones. La forma más fácil para instanciar y registrar de una sola vez es utilizando el método del ayudante `getStaticHelper()` :

    Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');

La primera vez que se instancia un controlador de acción, se disparará ViewRenderer para instanciar al objeto vista. Cada vez que el controlador es instanciado, se llama al método `init()` de ViewRenderer , que lo llevará a establecer la propiedad del controlador de acción, y llama a `addScriptPath()` con un path relativo al módulo actual; este será llamado con un prefijo de clase nombrada después del módulo actual, haciendo efectivamente el namespacing de todas las clases de ayudantes y filtros que define para el módulo.

Cad vez que llama a `postDispatch()` , este llamará a `render()` para la acción actual.

Como ejemplo, considere la siguiente clase:

    // Una clase controlador, módulo foo:
    class Foo_BarController extends Zend_Controller_Action
    {
        // Render bar/index.phtml por defecto; no se requiere acción
        public function indexAction()
        {
        }

        // Render bar/populate.phtml con la variable 'foo' establecida a 'bar'.
        // Dado que el objeto vista está definido en preDispatch(),
        // ya está disponible.
        public function populateAction()
        {
            $this->view->foo = 'bar';
        }
    }

    ...

    // en uno de sus scripts de vista:
    $this->foo(); // llama a Foo_View_Helper_Foo::foo()

El ViewRenderer también define una serie de accededores para permitir establecer y recuperar opciones de vista:

- `setView($view)` le permite establecer el objeto vista para ViewRenderer . Se vuelve como una propiedad de clase pública `$view` .

- `setNeverRender($flag = true)` puede ser utilizado para activar o desactivar globalmente el autorendering, es decir, para todos los controladores. Si es verdadero, `postDispatch()` no llamará automáticamente a `render()` en el controlador actual. `getNeverRender()` recupera el valor actual.

- `setNoRender($flag = true)` puede ser utilizado para activar o desactivar el autorendering. Si es verdadero, `postDispatch()` no llamará automáticamente a `render()` en el controlador actual. Este ajuste se reseteará cada vez que se llame a `preDispatch()` (es decir, usted necesita establecer este flag para cada controlador para el cual no quiera que el autorenderering se ejecute). `getNoRender()` recupera el valor actual.

- `setNoController($flag = true)` pude ser usado para decirle a `render()` que no busque el script de acción en un subdirectorio nombrado después de que el controlador (que es el comportamiento por defecto) `getNoController()` recupere el valor actual.

- `setNeverController($flag = true)` es análogo a `setNoController()` , pero trabaja a un nivel global -- es decir, que no se reseteará por cada acción ejecutada. `getNeverController()` recupera el valor actual.

- `setScriptAction($name)` puede ser utilizado para especificar el script de acción a renderizar. `$name` debe ser el nombre del script menos el sufijo del archivo (y sin el subdirectorio del controlador, a menos que noController se haya activado). Si no se ha especificado, busca un script de vista nombrado después de la acción en el objeto solicitud. `getScriptAction()` recupera el valor actual.

- `setResponseSegment($name)` puede ser utilizado para especificar qué segmento del objeto respuesta nombrado renderizar. Si no se especifica, se hace en el segmento por defecto. `getResponseSegment()` recupera el valor actual.

- `initView($path, $prefix, $options)` puede ser llamado para especificar el path base de las vistas, prefijos de clase para scripts de ayudantes y filtros, y las opciones de ViewRenderer . Puede pasar cualquiera de los siguientes flags: neverRender , noRender , noController , scriptAction , y responseSegment .

- `setRender($action = null, $name = null, $noController = false)` le permite establecer cualquier scriptAction , responseSegment , y noController en un pase. `direct()` es un alias a este método, permitiéndole llamar a este método fácilmente dede su controlador:

      // Render 'foo' en lugar del script de acción actual
      $this->_helper->viewRenderer('foo');

      // render form.phtml al segmento de respuesta de 'html', sin usar un
      // subdirectorio de scripts de controladores de acción:
      $this->_helper->viewRenderer('form', 'html', true);

  `setRender()` y `direct()` realmente no renderiza el script de vista, sino que establece indicaciones que `postDispatch()` y `render()` utlizarán para renderizar la vista.

El constructor le permite opcionalmente pasar el objeto vista y las opciones de ViewRenderer ; acepta los mismos flags que `initView()` :

    $view    = new Zend_View(array('encoding' => 'UTF-8'));
    $options = array('noController' => true, 'neverRender' => true);
    $viewRenderer =
        new Zend_Controller_Action_Helper_ViewRenderer($view, $options);

Hay varios métodos adicionales para personalizar especificaciones del path, usados para determinar el path base del script de vista para añadir al objeto vista, y el path del script de vista a usar cuando esté autodeterminando el script de vista a renderizar. Cada uno de estos métodos toma uno o más de los siguientes localizadores:

- :moduleDir hace referencia a la actual directorio base del módulo(por convención, el directorio padre del directorio del módulo controlador).

- :module hace referencia al nombre del módulo actual.

- :controller hace referencia al nombre del controlador actual.

- :action hace referencia al nombre de la acción actual.

- :suffix hace referencia al sufijo del script de vista (que puede ser definido via `setViewSuffix()` ).

Los métodos para controlar las especificaciones del path son:

- `setViewBasePathSpec($spec)` le permite cambiar la especificación del path utilizada para determinar el path base para añadir al objeto vista. La especificación por defecto es `:moduleDir/views` . Puede recuperar la especificación actual en cualquier momento usando `getViewBasePathSpec()` .

- `setViewScriptPathSpec($spec)` le permite cambiar el path de la especificación utilizada para determinar el path a un script de vista individual (menos el path de la base del script de vista). La especificación por defecto es `:controller/:action.:suffix` . Puede recuperar la especificación actual en cualquier momento usando `getViewScriptPathSpec()` .

- `setViewScriptPathNoControllerSpec($spec)` le permite cambiar el path de la especificación utilizado para determinar el path a un script de vista individual cuando noController está activado (menos el path base del script de vista). La especificación por defecto es `:action.:suffix` . Puede recuperar la especificación actual en cualquier momento usando `getViewScriptPathNoControllerSpec()` .

Para un control más refinado sobre el path de especificaciones, puede usar Zend_Filter_Inflector . Bajo el capó, ViewRenderer ya usa un inflector para realizar mapeos del path. Para interactuar con el inflector -- ya sea para establecerlo para uso propio, o para modificar el inflector por defecto, se pueden utilizar los siguientes métodos:

- `getInflector()` recupera el inflector. Si no existe todavía en ViewRenderer , se crea uno utilizando las reglas predeterminadas.

  Por defecto, utiliza reglas de referencias estáticas para el sufijo y directorio de módulos, así como una meta estática; esto permite que diversas propiedades de ViewRenderer tengan la capacidad de modificar dinámicamente al inflector.

- `setInflector($inflector, $reference)` permite establecer un inflector personalizado para usar con ViewRenderer . Si `$reference` es verdadero, establecerá el sufijo y directorio de módulos como referencias estáticas a las propiedades de ViewRenderer , así como al objetivo.

### Convenciones por Defecto para Lookup

El ViewRenderer hace algún tipo de normalización del path para facilitar la búsqueda de los scripts de vista. Las reglas predeterminadas son los siguientes:

- :module : MixedCase y camelCasedWords están separados por guiones, y el string completo se convierte a minúsculas. Por ejemplo: "FooBarBaz" pasa a ser "foo-bar-baz".

  Internamente, el inflector utiliza los filtros `Zend_Filter_Word_CamelCaseToDash` y `Zend_Filter_StringToLower` .

- :controller : MixedCase y camelCasedWords están separados por guiones; los subrayados se convierten en separadores de directorio , y el string emitido a minúsculas. Ejemplos: " `FooBar` " pasa a ser "foo-bar"; " `FooBar_Admin` " pasa a ser " `foo-bar/admin` ".

  Internamente, el inflector utiliza los filtros `Zend_Filter_Word_CamelCaseToDash` , `Zend_Filter_Word_UnderscoreToSeparator` , y `Zend_Filter_StringToLower` .

- :action : MixedCase y camelCasedWords están separados por guiones; los caracteres no alfanuméricos son traducidos a guiones, y el string emitido a minúsculas. Ejemplos: "fooBar" pasa a ser "foo-bar"; "foo-barBaz" pasa a ser "foo-bar-baz".

  Internamente, el inflector utiliza los filtros `Zend_Filter_Word_CamelCaseToDash` , `Zend_Filter_PregReplace` , y `Zend_Filter_StringToLower` .

Los últimos temas en la API de ViewRenderer son los métodos para determinar realmente los paths de los scripts de vista y el rendering de las vistas. Estos incluyen:

- `renderScript($script, $name)` permite renderizar un script con una ruta que especifique, opcionalmente a un segmento nombrado del path. Cuando se utiliza este método, ViewRenderer no autodetermina el nombre del script, en cambio pasa directamente a `$script` el argumento directamente al método del objeto vista `render()` .

  Una vez que la vista ha sido renderizada al objeto respuesta, se establece noRender para evitar accidentalmente renderizar el mismo script de vista varias veces.

  Por defecto, `Zend_Controller_Action::renderScript()` le delega a ViewRenderer el método `renderScript()` .

- `getViewScript($action, $vars)` crea el path a un script de vista basado en la acción pasada y/o cualquier variables pasadas en `$vars` . Las claves para este array pueden incluir cualquiera de las claves de especificación de paths ('moduleDir', 'module', 'controller', 'action', y 'suffix'). Se utilizarán cualquiera de la variables pasadas; de lo contrario, se utilizarán valores basados en la petición actual.

  `getViewScript()` utilizará tanto a viewScriptPathSpec o viewScriptPathNoControllerSpec sobre la base establecida del flag noController .

  Los delimitadores de palabras encontrados en un módulo, controlador o nombres de acción serán reemplazados por guiones ('-'). Así pues, si tiene el nombre de controlador ' `foo.bar` ' y la acción ' `baz:bat` ', utilizando la especificación por defecto del path se traducirá en un path al script de vista ' `foo-bar/baz-bat.phtml` '.

  Por defecto, `Zend_Controller_Action::getViewScript()` delega el método `getViewScript()` de ViewRenderer .

- `render($action, $name, $noController)` comprueba primero para ver si bien `$name` o `$noController` se han pasado, y si es así, establece los flags apropiados (responseSegment y noController, respectivamente) en ViewRenderer . A continuación, pasa el argumento `$action` , si hay alguno, a `getViewScript()` . Por último, pasa el path calculado del script de vista a `renderScript()` .

  Hay que ser conscientes de los efectos secundarios al usar `render()` : los valores que usted pasa para el nombre del segmento respuesta y para el flag noController persistirán en el objeto. Además, noRender será establecido después de completar la renderización.

  Por defecto, `Zend_Controller_Action::render()` delega a ViewRenderer el método `render()` .

- `renderBySpec($action, $vars, $name)` permite pasar variables de especificación del path a fin de determinar el path para la creación del script de vista. Este pasa `$action` y `$vars` a `getScriptPath()` , y luego pasa el path del script resultante y `$name` a `renderScript()` .

## Ejemplos Uso Básico

### Uso Básico

En lo más básico, usted simplemente inicializa y registra el ayudante ViewRenderer con el ayudante broker en su bootstrap, y luego establecer las variables en sus métodos de acción.

    // En su bootstrap:
    Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');

    ...

    // 'foo' módulo, 'bar' controlador:
    class Foo_BarController extends Zend_Controller_Action
    {
        // Render bar/index.phtml por defecto; no se requieren acciones
        public function indexAction()
        {
        }

        // Render bar/populate.phtml la variable 'foo' establecida a 'bar'.
        // Dado que el objeto fue definido en preDispatch(), está disponible.
        public function populateAction()
        {
            $this->view->foo = 'bar';
        }

        // No hace rendering, ya que salta a otra acción; la nueva acción
        // realizará cualquier rendering
        public function bazAction()
        {
            $this->_forward('index');
        }

        // No hace rendering, ya que redirecciona a otra ubicación
        public function batAction()
        {
            $this->_redirect('/index');
        }
    }

### Convenciones de Nombres: Delimitadores de Palabras en Controladores y Nombres de Acción

Si su controlador o nombre de acción está compuesto por varias palabras, el despachador exige que estos sean separados de la URL por un path específico y caracteres delimitadores de palabras. El ViewRenderer reemplaza cualquier delimitador de paths encontrado en el nombre del controlador con el delimitador actual ('/'), y cualquier delimitador de palabra encontrado con un guión ('-') cuando crea paths. Así, una llamada a la acción `/foo.bar/baz.bat` despachará a `FooBarController::bazBatAction()` en `FooBarController.php` , el cual renderizaría a `foo-bar/baz-bat.phtml` ; una llamada a la acción `/bar_baz/baz-bat` despachará a `Bar_BazController::bazBatAction()` en `Bar/BazController.php` (note la separación del path) y renderiza `bar/baz/baz-bat.phtml` .

Tener en cuenta que el en el segundo ejemplo, el módulo es todavía el módulo por defecto, pero que, debido a la existencia de un separador de paths, el controlador recibe el nombre `Bar_BazController` , en `Bar/BazController.php` . El ViewRenderer imita la jerarquía del directorio del controlador.

### Deshabilitando Autorender

Para algunas acciones o controladores, usted puede querer apagar el autorendering -- por ejemplo, si quiere emitir un tipo diferente de salida ( XML , JSON , etc), o si simplemente no desea emitir nada. Tiene dos opciones: apagar todos los casos de autorendering ( `setNeverRender()` ), o simplemente desactivarlo para la acción actual ( `setNoRender()` ).

    // Baz clase del controlador, bar módulo:
    class Bar_BazController extends Zend_Controller_Action
    {
        public function fooAction()
        {
            // No auto renderize esta acción
            $this->_helper->viewRenderer->setNoRender();
        }
    }

    // Bat clase del controlador, bar módulo:
    class Bar_BatController extends Zend_Controller_Action
    {
        public function preDispatch()
        {
            // Nunca auto renderizar las acciones de este controlador
            $this->_helper->viewRenderer->setNoRender();
        }
    }

En muchos casos, no tiene sentido desactivar el autorendering globalmente (ala `setNeverRender()` ), y la única cosa que puede ganar de ViewRenderer es el autosetup del objeto de vista.

### Eligiendo Un Script de Vista Diferente

Algunas situaciones requieren renderizar un script diferente al llamado después de la acción. Por ejemplo, si tiene un controlador que tiene tanto las acciones de agregar y de editar, ambos pueden mostrar la misma vista 'form', aunque con diferentes valores establecidos. Puede cambiar fácilmente el nombre del script usado tanto con `setScriptAction()` , `setRender()` , o llamando al ayudante como un método, que invocará a `setRender()` .

    // Bar clase controlador, foo módulo:
    class Foo_BarController extends Zend_Controller_Action
    {
        public function addAction()
        {
            // Render 'bar/form.phtml' en lugar de 'bar/add.phtml'
            $this->_helper->viewRenderer('form');
        }

        public function editAction()
        {
            // Render 'bar/form.phtml' en lugar de 'bar/edit.phtml'
            $this->_helper->viewRenderer->setScriptAction('form');
        }

        public function processAction()
        {
            // hacer alguna validación...
            if (!$valid) {
                // Render 'bar/form.phtml' en lugar de 'bar/process.phtml'
                $this->_helper->viewRenderer->setRender('form');
                return;
            }

            // de otra manera, continuar procesando...
        }

    }

### Modificando la Vista Registrada

¿Y si se necesita modificar el objeto vista -- por ejemplo, cambiar el ayudante de paths, o la codificación?. Puede hacerlo ya sea por modificar el objeto vista establecido en su controlador, o arrebatándole el objeto vista a ViewRenderer ; ambas son referencias al mismo objeto.

    // Bar clase controlador, foo módulo:
    class Foo_BarController extends Zend_Controller_Action
    {
        public function preDispatch()
        {
            // cambiar la codificavión de la vista
            $this->view->setEncoding('UTF-8');
        }

        public function bazAction()
        {
            // Obtener el objeto vista y establecer
            // el callback de escape a 'htmlspecialchars'
            $view = $this->_helper->viewRenderer->view;
            $view->setEscape('htmlspecialchars');
        }
    }

## Ejemplos de Uso Avanzado

### Cambiando las Especificaciones del Path

En algunas circunstancias, puede decidir que las especificaciones del path por defecto no se adaptan a su sitio. Por ejemplo, usted puede querer tener un árbol único de plantillas al que puede dar acceso a sus diseñadores (esto es muy típico cuando se utiliza Smarty , por ejemplo). En ese caso, puede querer embeber los datos de la especificación del path base de la vista, y crear una especificación alternativa para el script de vista del path ellos mismos.

Para los fines de este ejemplo, supongamos que el path base de las vistas debería ser ' `/opt/vendor/templates` ', y que desea para que los scripts de vista sean referenciados por ' `:moduleDir/:controller/:action.:suffix` '; si el flag noController ha sido establecido, quiere renderizar fuera del nivel superior en lugar de en un subdirectorio ( `':action.:suffix` '). Por último, que quiere utilizar 'tpl' como el sufijo del nombre de archivo del script de vista.

    /**
     * En su bootstrap:
     */

    // Implementación de una vista diferente
    $view = new ZF_Smarty();

    $viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer($view);
    $viewRenderer->setViewBasePathSpec('/opt/vendor/templates')
                 ->setViewScriptPathSpec(':module/:controller/:action.:suffix')
                 ->setViewScriptPathNoControllerSpec(':action.:suffix')
                 ->setViewSuffix('tpl');
    Zend_Controller_Action_HelperBroker::addHelper($viewRenderer);

### Rendering Múltiples Scripts de Vista desde una Sola Acción

A veces, puede que necesite renderizar múltiples scripts de vista desde una sola acción. Esto es muy sencillo -- simplemente hacer múltiples llamadas a `render()` :

    class SearchController extends Zend_Controller_Action
    {
        public function resultsAction()
        {
            // Suponga que $this->model es el modelo actual
            $this->view->results =
                $this->model->find($this->_getParam('query', '');

            // render() por defecto lo delega al ViewRenderer
            // Render primero al from de búsqueda y luego los resultados
            $this->render('form');
            $this->render('results');
        }

        public function formAction()
        {
            // No hacer nada; ViewRenderer hace autorender del script de vista
        }
    }