Los ayudantes de acción (Action Helpers) permiten a los desarrolladores inyectar
funcionalidad en tiempo de ejecución y/o bajo demanda en cualquier controlador de
acción que extienda de Zend_Controller_Action. Los ayudantes
de acción tienen como objetivo minimizar la necesidad de extender el controlador de
acción abstracto para inyectar funcionalidad común del controlador de acción.
Existen varias formas de utilizar los ayudantes de acción. Los ayudantes de acción
emplean el uso de un sistema de corretaje (brokerage), similar al tipo de corretaje que
se ve en Zend_View_Helper,
y al de Zend_Controller_Plugin.
Los ayudantes de acción (al igual que Zend_View_Helper) pueden
cargarse y llamarse bajo demanda, o pueden instanciarse en el momento de la petición
(bootstrap) o en el momento de creación del controlador de acción
(init()). Para comprender esto con más detalle, consulte la
sección de uso a continuación.
Un ayudante puede inicializarse de varias formas distintas, según sus necesidades así como la funcionalidad de dicho ayudante.
El corredor de ayudantes (helper broker) se almacena como el miembro
$_helper de Zend_Controller_Action; use el
corredor para recuperar o invocar ayudantes. Algunos métodos para hacerlo incluyen:
-
Usar explícitamente
getHelper(). Simplemente pásele un nombre, y se devuelve un objeto ayudante:$flashMessenger = $this->_helper->getHelper('FlashMessenger'); $flashMessenger->addMessage('We did something in the last request'); -
Usar la funcionalidad
__get()del corredor de ayudantes y recuperar el ayudante como si fuera una propiedad miembro del corredor:$flashMessenger = $this->_helper->FlashMessenger; $flashMessenger->addMessage('We did something in the last request'); -
Finalmente, la mayoría de los ayudantes de acción implementan el método
direct(), el cual llamará a un método específico y predeterminado en el ayudante. En el ejemplo del FlashMessenger, este invoca aaddMessage():$this->_helper->FlashMessenger('We did something in the last request');
![]() |
Nota |
|---|---|
Todos los ejemplos anteriores son funcionalmente equivalentes. |
También puede instanciar ayudantes explícitamente. Es posible que desee hacer esto si utiliza el ayudante fuera de un controlador de acción, o si desea pasar un ayudante al corredor de ayudantes para que lo use cualquier acción. La instanciación se realiza como con cualquier otra clase de PHP.
Zend_Controller_Action_HelperBroker se encarga de los
detalles del registro de objetos ayudantes y rutas de ayudantes, así como de
recuperar ayudantes bajo demanda.
Para registrar un ayudante con el corredor, use addHelper():
Zend_Controller_Action_HelperBroker::addHelper($helper);
Por supuesto, instanciar y pasar ayudantes al corredor consume algo de tiempo y
recursos, por lo que existen dos métodos para automatizar un poco las cosas:
addPrefix() y addPath().
-
addPrefix()toma un prefijo de clase y lo usa para determinar una ruta donde se han definido las clases de ayudantes. Se asume que el prefijo sigue las convenciones de nomenclatura de clases de Zend Framework.// Add helpers prefixed with My_Action_Helpers in My/Action/Helpers/ Zend_Controller_Action_HelperBroker::addPrefix('My_Action_Helpers'); -
addPath()toma un directorio como primer argumento y un prefijo de clase como segundo argumento (por defecto 'Zend_Controller_Action_Helper'). Esto le permite asignar sus propios prefijos de clase a directorios específicos.// Add helpers prefixed with Helper in Plugins/Helpers/ Zend_Controller_Action_HelperBroker::addPath('./Plugins/Helpers', 'Helper');
Dado que estos métodos son estáticos, pueden invocarse en cualquier punto de la cadena del controlador con el fin de agregar ayudantes dinámicamente según sea necesario.
Internamente, el corredor de ayudantes utiliza una
instancia de PluginLoader para mantener las rutas. Puede recuperar el
PluginLoader usando el método estático getPluginLoader(),
o, alternativamente, inyectar una instancia personalizada de PluginLoader usando
setPluginLoader().
Para determinar si un ayudante existe en el corredor de ayudantes, use
hasHelper($name), donde $name es el
nombre corto del ayudante (sin el prefijo):
// Check if 'redirector' helper is registered with the broker:
if (Zend_Controller_Action_HelperBroker::hasHelper('redirector')) {
echo 'Redirector helper registered';
}
También existen dos métodos estáticos para recuperar ayudantes del corredor de
ayudantes: getExistingHelper() y
getStaticHelper().
getExistingHelper()
recuperará un ayudante solo si previamente ha sido invocado o registrado
explícitamente con el corredor de ayudantes; lanzará una excepción si no es así.
getStaticHelper() hace lo mismo que
getExistingHelper(), pero intentará instanciar el ayudante
si aún no ha sido registrado en la pila de ayudantes.
getStaticHelper() es una buena opción para recuperar
ayudantes que se desea configurar.
Ambos métodos toman un único argumento, $name, que es el
nombre corto del ayudante (sin el prefijo).
// Check if 'redirector' helper is registered with the broker, and fetch:
if (Zend_Controller_Action_HelperBroker::hasHelper('redirector')) {
$redirector =
Zend_Controller_Action_HelperBroker::getExistingHelper('redirector');
}
// Or, simply retrieve it, not worrying about whether or not it was
// previously registered:
$redirector =
Zend_Controller_Action_HelperBroker::getStaticHelper('redirector');
}
Finalmente, para eliminar un ayudante registrado del corredor, use
removeHelper($name), donde $name es el
nombre corto del ayudante (sin el prefijo):
// Conditionally remove the 'redirector' helper from the broker:
if (Zend_Controller_Action_HelperBroker::hasHelper('redirector')) {
Zend_Controller_Action_HelperBroker::removeHelper('redirector')
}
Zend Framework incluye varios ayudantes de acción por defecto: AutoComplete para automatizar respuestas de autocompletado AJAX; ContextSwitch y AjaxContext para servir formatos de respuesta alternativos para sus acciones; un FlashMessenger para manejar mensajes flash de sesión; Json para codificar y enviar respuestas JSON; un Redirector, que proporciona diferentes implementaciones para redirigir a páginas internas y externas desde su aplicación; y un ViewRenderer para automatizar el proceso de configuración del objeto de vista en sus controladores y la renderización de vistas.
El ayudante ActionStack le permite enviar peticiones al plugin del controlador frontal ActionStack, ayudándole efectivamente a crear una cola de acciones para ejecutar durante la petición. El ayudante le permite agregar acciones ya sea especificando nuevos objetos de petición o conjuntos de acción - controlador - módulo.
![]() |
Invocar el ayudante ActionStack inicializa el plugin ActionStack |
|---|---|
Invocar el ayudante ActionStack registra implícitamente el plugin ActionStack -- lo que significa que no necesita registrar explícitamente el plugin ActionStack para usar esta funcionalidad. |
Ejemplo 24.2. Agregar una tarea usando nombres de acción, controlador y módulo
A menudo, es más sencillo simplemente especificar la acción, el controlador y el
módulo (y parámetros de petición opcionales), tal como lo haría al llamar a
Zend_Controller_Action::_forward():
class FooController extends Zend_Controller_Action
{
public function barAction()
{
// Add two actions to the stack
// Add call to /foo/baz/bar/baz
// (FooController::bazAction() with request var bar == baz)
$this->_helper->actionStack('baz',
'foo',
'default',
array('bar' => 'baz'));
// Add call to /bar/bat
// (BarController::batAction())
$this->_helper->actionStack('bat', 'bar');
}
}
Ejemplo 24.3. Agregar una tarea usando un objeto de petición
A veces la naturaleza OOP de un objeto de petición tiene más sentido; puede pasar dicho objeto al ayudante ActionStack también.
class FooController extends Zend_Controller_Action
{
public function barAction()
{
// Add two actions to the stack
// Add call to /foo/baz/bar/baz
// (FooController::bazAction() with request var bar == baz)
$request = clone $this->getRequest();
// Don't set controller or module; use current values
$request->setActionName('baz')
->setParams(array('bar' => 'baz'));
$this->_helper->actionStack($request);
// Add call to /bar/bat
// (BarController::batAction())
$request = clone $this->getRequest();
// don't set module; use current value
$request->setActionName('bat')
->setControllerName('bar');
$this->_helper->actionStack($request);
}
}
Muchas bibliotecas javascript de AJAX ofrecen funcionalidad para proporcionar autocompletado, mediante la cual se muestra una lista de posibles resultados coincidentes a medida que el usuario escribe. El ayudante AutoComplete tiene como objetivo simplificar la devolución de respuestas aceptables para dichos métodos.
Dado que no todas las bibliotecas JS implementan el autocompletado de la misma manera, el ayudante AutoComplete proporciona alguna funcionalidad base abstracta necesaria para muchas bibliotecas, e implementaciones concretas para bibliotecas individuales. Los tipos de retorno son generalmente arreglos JSON de cadenas, arreglos JSON de arreglos (siendo cada arreglo miembro un arreglo asociativo de metadatos usado para crear la lista de selección), o HTML.
El uso básico para cada implementación es el mismo:
class FooController extends Zend_Controller_Action
{
public function barAction()
{
// Perform some logic...
// Encode and send response;
$this->_helper->autoCompleteDojo($data);
// Or explicitly:
$response = $this->_helper->autoCompleteDojo
->sendAutoCompletion($data);
// Or simply prepare autocompletion response:
$response = $this->_helper->autoCompleteDojo
->prepareAutoCompletion($data);
}
}
Por defecto, el autocompletado realiza lo siguiente:
Deshabilita los layouts y el ViewRenderer.
Establece las cabeceras de respuesta apropiadas.
Establece el cuerpo de la respuesta con los datos de autocompletado codificados o formateados.
Envía la respuesta.
Los métodos disponibles del ayudante incluyen:
disableLayouts()se puede usar para deshabilitar los layouts y el ViewRenderer. Típicamente, esto se llama dentro deprepareAutoCompletion().encodeJson($data, $keepLayouts = false)codificará los datos a JSON, habilitando o deshabilitando opcionalmente los layouts. Típicamente, esto se llama dentro deprepareAutoCompletion().prepareAutoCompletion($data, $keepLayouts = false)se usa para preparar los datos en el formato de respuesta necesario para la implementación concreta, habilitando o deshabilitando opcionalmente los layouts. El valor de retorno variará según la implementación.sendAutoCompletion($data, $keepLayouts = false)se usa para enviar los datos en el formato de respuesta necesario para la implementación concreta. Llama aprepareAutoCompletion(), y luego envía la respuesta.direct($data, $sendNow = true, $keepLayouts = false)se usa al llamar al ayudante como un método del corredor de ayudantes. La bandera$sendNowse usa para determinar si se debe llamar asendAutoCompletion()oprepareAutoCompletion(), respectivamente.
Actualmente, AutoComplete soporta las bibliotecas AJAX Dojo y Scriptaculous.
Dojo no tiene un widget de AutoCompletion propiamente dicho, pero cuenta con dos widgets que pueden realizar AutoCompletion: ComboBox y FilteringSelect. En ambos casos, requieren un almacén de datos que implemente QueryReadStore; para más información sobre estos temas, consulte la documentación de dojo.data.
En Zend Framework, puede pasar un simple arreglo indexado al ayudante AutoCompleteDojo, y este devolverá una respuesta JSON adecuada para usar con dicho almacén:
// within a controller action: $this->_helper->autoCompleteDojo($data);
Ejemplo 24.4. Autocompletado con Dojo usando el MVC de Zend
El autocompletado con Dojo a través del MVC de Zend requiere varias cosas: generar un objeto de formulario para el ComboBox en el que se desea el autocompletado, una acción de controlador para servir los resultados de autocompletado, crear un QueryReadStore personalizado para conectar con la acción de autocompletado, y generar el javascript necesario para inicializar el autocompletado en el lado del servidor.
Primero, veamos el javascript necesario. Dojo ofrece un framework completo
para crear javascript OOP, tal como lo hace Zend
Framework para PHP. Parte de esto es la capacidad de crear
pseudo-espacios de nombres usando la jerarquía de directorios. Crearemos un
directorio 'custom' al mismo nivel que el directorio Dojo que forma parte de
la distribución de Dojo. Dentro de ese directorio, crearemos un archivo
javascript, TestNameReadStore.js, con el siguiente
contenido:
dojo.provide("custom.TestNameReadStore");
dojo.declare("custom.TestNameReadStore", dojox.data.QueryReadStore, {
fetch:function (request) {
request.serverQuery = { test:request.query.name };
return this.inherited("fetch", arguments);
}
});
Esta clase es simplemente una extensión del propio QueryReadStore de Dojo, que en sí mismo es una clase abstracta. Simplemente definimos un método de petición, y lo asignamos al elemento 'test'.
A continuación, creemos el elemento de formulario para el cual queremos autocompletado:
class TestController extends Zend_Controller_Action
{
protected $_form;
public function getForm()
{
if (null === $this->_form) {
$this->_form = new Zend_Form();
$this->_form->setMethod('get')
->setAction(
$this->getRequest()->getBaseUrl() . '/test/process'
)
->addElements(array(
'test' => array('type' => 'text', 'options' => array(
'filters' => array('StringTrim'),
'dojoType' => array('dijit.form.ComboBox'),
'store' => 'testStore',
'autoComplete' => 'false',
'hasDownArrow' => 'true',
'label' => 'Your input:',
)),
'go' => array('type' => 'submit',
'options' => array('label' => 'Go!'))
));
}
return $this->_form;
}
}
Aquí, simplemente creamos un formulario con los métodos 'test' y 'go'. El
método 'test' agrega varios atributos especiales, específicos de Dojo:
dojoType, store, autoComplete y hasDownArrow. dojoType se usa para indicar
que estamos creando un ComboBox, y lo enlazaremos a un almacén de datos
(clave 'store') de 'testStore' -- más sobre esto más adelante. Especificar
'autoComplete' como FALSE le indica a Dojo que no
seleccione automáticamente la primera coincidencia, sino que muestre una
lista de coincidencias. Finalmente, 'hasDownArrow' crea una flecha hacia
abajo similar a un cuadro de selección para que podamos mostrar y ocultar
las coincidencias.
Agreguemos un método para mostrar el formulario, así como un punto final para procesar el autocompletado:
class TestController extends Zend_Controller_Action
{
// ...
/**
* Landing page
*/
public function indexAction()
{
$this->view->form = $this->getForm();
}
public function autocompleteAction()
{
if ('ajax' != $this->_getParam('format', false)) {
return $this->_helper->redirector('index');
}
if ($this->getRequest()->isPost()) {
return $this->_helper->redirector('index');
}
$match = trim($this->getRequest()->getQuery('test', ''));
$matches = array();
foreach ($this->getData() as $datum) {
if (0 === strpos($datum, $match)) {
$matches[] = $datum;
}
}
$this->_helper->autoCompleteDojo($matches);
}
}
En nuestra autocompleteAction() hacemos varias
cosas. Primero, verificamos que se trate de una petición post, y que exista
un parámetro 'format' establecido con el valor 'ajax'; esto simplemente
ayuda a reducir consultas espurias a la acción. Luego, verificamos un
parámetro 'test', y lo comparamos contra nuestros datos. (Omito
deliberadamente la implementación de getData() aquí
-- podría ser cualquier tipo de fuente de datos.) Finalmente, enviamos
nuestras coincidencias a nuestro ayudante de AutoCompletion.
Ahora que tenemos todas las piezas en el backend, veamos qué necesitamos entregar en nuestro script de vista para la página de aterrizaje. Primero, necesitamos configurar nuestro almacén de datos, luego renderizar nuestro formulario, y finalmente asegurarnos de que se carguen las bibliotecas Dojo apropiadas -- incluyendo nuestro almacén de datos personalizado. Veamos el script de vista, que comenta los pasos:
<?php // setup our data store: ?>
<div dojoType="custom.TestNameReadStore" jsId="testStore"
url="<?php echo $this->baseUrl() ?>/unit-test/autocomplete/format/ajax"
requestMethod="get"></div>
<?php // render our form: ?>
<?php echo $this->form ?>
<?php // setup Dojo-related CSS to load in HTML head: ?>
<?php $this->headStyle()->captureStart() ?>
@import "<?php echo $this->baseUrl()
?>/javascript/dijit/themes/tundra/tundra.css";
@import "<?php echo $this->baseUrl() ?>/javascript/dojo/resources/dojo.css";
<?php $this->headStyle()->captureEnd() ?>
<?php // setup javascript to load in HTML head, including all required
// Dojo libraries: ?>
<?php $this->headScript()
->setAllowArbitraryAttributes(true)
->appendFile($this->baseUrl() . '/javascript/dojo/dojo.js',
'text/javascript',
array('djConfig' => 'parseOnLoad: true'))
->captureStart() ?>
djConfig.usePlainJson=true;
dojo.registerModulePath("custom","../custom");
dojo.require("dojo.parser");
dojo.require("dojox.data.QueryReadStore");
dojo.require("dijit.form.ComboBox");
dojo.require("custom.TestNameReadStore");
<?php $this->headScript()->captureEnd() ?>
Observe las llamadas a ayudantes de vista como headStyle y headScript; estos son marcadores de posición (placeholders), que luego podemos renderizar en la sección HTML head de nuestro script de vista de layout.
Ahora tenemos todas las piezas para hacer que el autocompletado de Dojo funcione.
Scriptaculous espera una respuesta HTML en un formato específico.
El ayudante a usar con esta biblioteca es 'AutoCompleteScriptaculous'. Simplemente proporciónele un arreglo de datos, y el ayudante creará una respuesta HTML compatible con Ajax.Autocompleter.
El ayudante de acción ContextSwitch está pensado para facilitar la devolución de diferentes formatos de respuesta según la petición. El ayudante AjaxContext es una versión especializada de ContextSwitch que facilita la devolución de respuestas a XmlHttpRequests.
Para habilitar cualquiera de los dos, debe proporcionar indicaciones en su controlador sobre qué acciones pueden responder a qué contextos. Si una petición entrante indica un contexto válido para la acción dada, el ayudante entonces:
Deshabilitará los layouts, si están habilitados.
Establecerá un sufijo de vista alternativo, lo que efectivamente requiere un script de vista independiente para el contexto.
Enviará las cabeceras de respuesta apropiadas para el contexto deseado.
Opcionalmente, invocará callbacks especificados para configurar el contexto y/o realizar el postprocesamiento.
Como ejemplo, consideremos el siguiente controlador:
class NewsController extends Zend_Controller_Action
{
/**
* Landing page; forwards to listAction()
*/
public function indexAction()
{
$this->_forward('list');
}
/**
* List news items
*/
public function listAction()
{
}
/**
* View a news item
*/
public function viewAction()
{
}
}
Supongamos que queremos que listAction() también esté
disponible en formato XML. En lugar de crear una acción
diferente, podemos indicar que puede devolver una respuesta
XML:
class NewsController extends Zend_Controller_Action
{
public function init()
{
$contextSwitch = $this->_helper->getHelper('contextSwitch');
$contextSwitch->addActionContext('list', 'xml')
->initContext();
}
// ...
}
Esto hará lo siguiente:
Establecerá la cabecera de respuesta 'Content-Type' a '
application/xml'.Cambiará el sufijo de vista a '
xml.phtml' (o, si usa un sufijo de vista alternativo, 'xml.[su sufijo]').
Ahora, necesitará crear un nuevo script de vista, 'news/list.xml.phtml',
que creará y renderizará el XML.
Para determinar si una petición debe iniciar un cambio de contexto, el ayudante verifica un token en el objeto de petición. Por defecto, busca el parámetro 'format', aunque esto puede configurarse. Esto significa que, en la mayoría de los casos, para activar un cambio de contexto, puede agregar un parámetro 'format' a su petición:
Mediante parámetro de URL:
/news/list/format/xml(recuerde, el esquema de enrutamiento por defecto permite pares clave-valor arbitrarios después de la acción)Mediante parámetro
GET: /news/list?format=xml
ContextSwitch le permite especificar contextos arbitrarios, incluyendo qué cambio de sufijo ocurrirá (si acaso), cualquier cabecera de respuesta que deba enviarse, y callbacks arbitrarios para la inicialización y el postprocesamiento.
Por defecto, hay dos contextos disponibles para el ayudante ContextSwitch: json y XML.
-
JSON. El contexto JSON establece la cabecera de respuesta 'Content-Type' a '
application/json', y el sufijo del script de vista a 'json.phtml'.Sin embargo, por defecto no se requiere ningún script de vista. Simplemente serializará todas las variables de vista, y emitirá la respuesta JSON de inmediato.
Este comportamiento se puede deshabilitar desactivando la serialización automática de JSON:
$this->_helper->contextSwitch()->setAutoJsonSerialization(false);
XML. El contexto XML establece la cabecera de respuesta 'Content-Type' a '
application/xml', y el sufijo del script de vista a 'xml.phtml'. Necesitará crear un nuevo script de vista para el contexto.
A veces, los contextos por defecto no son suficientes. Por ejemplo, es posible que desee devolver YAML, PHP serializado, un feed RSS o ATOM, etc. ContextSwitch le permite hacerlo.
La forma más fácil de agregar un nuevo contexto es mediante el método
addContext(). Este método toma dos argumentos, el nombre
del contexto, y una especificación en forma de arreglo. La especificación debe
incluir uno o más de los siguientes:
suffix: el sufijo a anteponer al sufijo de vista por defecto registrado en el ViewRenderer.
headers: un arreglo de pares cabecera-valor que desea que se envíen como parte de la respuesta.
-
callbacks: un arreglo que contiene una o más de las claves 'init' o 'post', apuntando a callbacks PHP válidos que pueden usarse para la inicialización del contexto y/o el postprocesamiento.
Los callbacks de inicialización ocurren cuando ContextSwitch detecta el contexto. Puede usarlo para realizar lógica arbitraria que deba ocurrir. Como ejemplo, el contexto JSON usa un callback para deshabilitar el ViewRenderer cuando la serialización automática de JSON está activada.
El postprocesamiento ocurre durante la rutina
postDispatch()de la acción, y se puede usar para realizar lógica arbitraria. Como ejemplo, el contexto JSON usa un callback para determinar si la serialización automática de JSON está activada; si es así, serializa las variables de vista a JSON y envía la respuesta, pero si no, vuelve a habilitar el ViewRenderer.
Existen diversos métodos para interactuar con los contextos:
addContext($context, array $spec): agrega un nuevo contexto. Lanza una excepción si el contexto ya existe.setContext($context, array $spec): agrega un nuevo contexto o sobrescribe uno existente. Usa la misma especificación queaddContext().addContexts(array $contexts): agrega varios contextos a la vez. El arreglo$contextsdebe ser un arreglo de pares contexto-especificación. Si alguno de los contextos ya existe, lanzará una excepción.setContexts(array $contexts): agrega nuevos contextos y sobrescribe los existentes. Usa la misma especificación queaddContexts().hasContext($context): devuelveTRUEsi el contexto existe,FALSEen caso contrario.getContext($context): recupera un único contexto por nombre. Devuelve un arreglo siguiendo la especificación usada enaddContext().getContexts(): recupera todos los contextos. Devuelve un arreglo de pares contexto-especificación.removeContext($context): elimina un único contexto por nombre. DevuelveTRUEsi tiene éxito,FALSEsi no se encontró el contexto.clearContexts(): elimina todos los contextos.
Existen dos mecanismos para establecer los contextos disponibles. Puede crear manualmente arreglos en su controlador, o usar varios métodos en ContextSwitch para ensamblarlos.
El método principal para agregar relaciones acción-contexto es
addActionContext(). Espera dos argumentos, la acción a
la que se agrega el contexto, y ya sea el nombre de un contexto o un arreglo
de contextos. Como ejemplo, considere la siguiente clase de controlador:
class FooController extends Zend_Controller_Action
{
public function listAction()
{
}
public function viewAction()
{
}
public function commentsAction()
{
}
public function updateAction()
{
}
}
Supongamos que queremos agregar un contexto XML a la acción
'list', y contextos XML y JSON a la
acción 'comments'. Podemos hacerlo en el método
init():
class FooController extends Zend_Controller_Action
{
public function init()
{
$this->_helper->contextSwitch()
->addActionContext('list', 'xml')
->addActionContext('comments', array('xml', 'json'))
->initContext();
}
}
Alternativamente, podría simplemente definir la propiedad de arreglo
$contexts:
class FooController extends Zend_Controller_Action
{
public $contexts = array(
'list' => array('xml'),
'comments' => array('xml', 'json')
);
public function init()
{
$this->_helper->contextSwitch()->initContext();
}
}
Lo anterior implica menos sobrecarga, pero también es más propenso a posibles errores.
Los siguientes métodos pueden usarse para construir los mapeos de contexto:
-
addActionContext($action, $context): marca uno o más contextos como disponibles para una acción. Si ya existen mapeos, simplemente se agrega a esos mapeos.$contextpuede ser un único contexto, o un arreglo de contextos.Un valor de
TRUEpara el contexto marcará todos los contextos disponibles como disponibles para la acción.Un valor vacío para
$contextdeshabilitará todos los contextos para la acción dada. setActionContext($action, $context): marca uno o más contextos como disponibles para una acción. Si ya existen mapeos, los reemplaza con los especificados.$contextpuede ser un único contexto, o un arreglo de contextos.addActionContexts(array $contexts): agrega varios pares acción-contexto a la vez.$contextsdebe ser un arreglo asociativo de pares acción-contexto. Delega enaddActionContext(), lo que significa que si ya existen mapeos, se agrega a ellos.setActionContexts(array $contexts): actúa comoaddActionContexts(), pero sobrescribe los pares acción-contexto existentes.hasActionContext($action, $context): determina si una acción particular tiene un contexto dado.getActionContexts($action = null): devuelve ya sea todos los contextos para una acción dada, o todos los pares acción-contexto.removeActionContext($action, $context): elimina uno o más contextos de una acción dada.$contextpuede ser un único contexto o un arreglo de contextos.clearActionContexts($action = null): elimina todos los contextos de una acción dada, o de todas las acciones con contextos.
Para inicializar el cambio de contexto, necesita llamar a
initContext() en su controlador de acción:
class NewsController extends Zend_Controller_Action
{
public function init()
{
$this->_helper->contextSwitch()->initContext();
}
}
En algunos casos, es posible que desee forzar el contexto usado; por ejemplo,
puede que solo desee permitir el contexto XML si el cambio
de contexto está activado. Puede hacerlo pasando el contexto a
initContext():
$contextSwitch->initContext('xml');
Se pueden usar varios métodos para modificar el comportamiento del ayudante ContextSwitch. Estos incluyen:
-
setAutoJsonSerialization($flag): Por defecto, los contextos JSON serializarán todas las variables de vista a notación JSON y las devolverán como respuesta. Si desea crear su propia respuesta, debe desactivar esto; esto debe hacerse antes de la llamada ainitContext().$contextSwitch->setAutoJsonSerialization(false); $contextSwitch->initContext();
Puede recuperar el valor de la bandera con
getAutoJsonSerialization(). -
setSuffix($context, $suffix, $prependViewRendererSuffix): Con este método, puede especificar un sufijo diferente para usar en un contexto dado. El tercer argumento se usa para indicar si se debe anteponer el sufijo actual del ViewRenderer con el nuevo sufijo; esta bandera está habilitada por defecto.Pasar un valor vacío al sufijo hará que solo se use el sufijo del ViewRenderer.
-
addHeader($context, $header, $content): Agrega una cabecera de respuesta para un contexto dado.$headeres el nombre de la cabecera, y$contentes el valor a pasar para esa cabecera.Cada contexto puede tener múltiples cabeceras;
addHeader()agrega cabeceras adicionales a la pila de cabeceras del contexto.Si la
$headerespecificada ya existe para el contexto, se lanzará una excepción. setHeader($context, $header, $content):setHeader()actúa igual queaddHeader(), salvo que permite sobrescribir cabeceras de contexto existentes.addHeaders($context, array $headers): Agrega varias cabeceras a la vez a un contexto dado. Delega enaddHeader(), por lo que si la cabecera ya existe, se lanzará una excepción.$headerses un arreglo de pares cabecera-contexto.setHeaders($context, array $headers.): comoaddHeaders(), salvo que delega ensetHeader(), permitiéndole sobrescribir cabeceras existentes.getHeader($context, $header): recupera el valor de una cabecera para un contexto dado. DevuelveNULLsi no se encuentra.removeHeader($context, $header): elimina una única cabecera para un contexto dado.clearHeaders($context, $header): elimina todas las cabeceras para un contexto dado.setCallback($context, $trigger, $callback): establece un callback en un disparador (trigger) dado para un contexto dado. Los disparadores pueden ser 'init' o 'post' (indicando que el callback se llamará en la inicialización del contexto o en postDispatch).$callbackdebe ser un callback PHP válido.setCallbacks($context, array $callbacks): establece varios callbacks para un contexto dado.$callbacksdebe ser pares disparador-callback. En realidad, la cantidad máxima de callbacks que se pueden registrar es dos, uno para la inicialización y otro para el postprocesamiento.getCallback($context, $trigger): recupera un callback para un disparador dado en un contexto dado.getCallbacks($context): recupera todos los callbacks para un contexto dado. Devuelve un arreglo de pares disparador-callback.removeCallback($context, $trigger): elimina un callback para un disparador y contexto dados.clearCallbacks($context): elimina todos los callbacks para un contexto dado.-
setContextParam($name): establece el parámetro de petición a verificar al determinar si se ha solicitado un cambio de contexto. El valor por defecto es 'format', pero este accesor se puede usar para establecer un valor alternativo.getContextParam()se puede usar para recuperar el valor actual. -
setAutoDisableLayout($flag): Por defecto, los layouts se deshabilitan cuando ocurre un cambio de contexto; esto se debe a que normalmente los layouts solo se usarán para devolver respuestas normales, y no tienen sentido en contextos alternativos. Sin embargo, si desea usar layouts (quizás tenga un layout para el nuevo contexto), puede cambiar este comportamiento pasando un valorFALSEasetAutoDisableLayout(). Debe hacer esto antes de llamar ainitContext().Para obtener el valor de esta bandera, use el accesor
getAutoDisableLayout(). getCurrentContext()se puede usar para determinar qué contexto fue detectado, si acaso. Esto devuelveNULLsi no ocurrió ningún cambio de contexto, o si se llama antes de que se haya invocadoinitContext().
El ayudante AjaxContext extiende ContextSwitch, por lo que toda la funcionalidad listada para ContextSwitch está disponible en él. Sin embargo, hay algunas diferencias clave.
Primero, usa una propiedad diferente del controlador de acción para
determinar los contextos, $ajaxable. Esto es para que
pueda tener diferentes contextos usados para peticiones AJAX
frente a peticiones HTTP normales. Los diversos métodos
*ActionContext()* de
AjaxContext escribirán en esta propiedad.
Segundo, solo se activará si ha ocurrido un XmlHttpRequest, según lo
determinado por el método isXmlHttpRequest() del
objeto de petición. Por lo tanto, si el parámetro de contexto ('format') se
pasa en la petición, pero la petición no se realizó como un
XmlHttpRequest, no se activará ningún cambio de contexto.
Tercero, AjaxContext agrega un contexto adicional,
HTML. En este contexto, establece el sufijo a
'ajax.phtml' para diferenciar el contexto de una
petición normal. No se devuelven cabeceras adicionales.
Ejemplo 24.5. Permitir que las acciones respondan a peticiones Ajax
En el siguiente ejemplo, permitimos que las peticiones a las acciones 'view', 'form' y 'process' respondan a peticiones AJAX. En los dos primeros casos, 'view' y 'form', devolveremos fragmentos HTML con los que actualizar la página; en el último, devolveremos JSON.
class CommentController extends Zend_Controller_Action
{
public function init()
{
$ajaxContext = $this->_helper->getHelper('AjaxContext');
$ajaxContext->addActionContext('view', 'html')
->addActionContext('form', 'html')
->addActionContext('process', 'json')
->initContext();
}
public function viewAction()
{
// Pull a single comment to view.
// When AjaxContext detected, uses the comment/view.ajax.phtml
// view script.
}
public function formAction()
{
// Render the "add new comment" form.
// When AjaxContext detected, uses the comment/form.ajax.phtml
// view script.
}
public function processAction()
{
// Process a new comment
// Return the results as JSON; simply assign the results as
// view variables, and JSON will be returned.
}
}
En el lado del cliente, su biblioteca AJAX simplemente
solicitará los puntos finales '/comment/view',
'/comment/form', y
'/comment/process', y pasará el parámetro 'format':
'/comment/view/format/html',
'/comment/form/format/html',
'/comment/process/format/json'. (O puede pasar el
parámetro a través de la cadena de consulta: por ejemplo, "?format=json".)
Suponiendo que su biblioteca envía la cabecera 'X-Requested-With: XmlHttpRequest', estas acciones devolverán entonces el formato de respuesta apropiado.
El ayudante FlashMessenger le permite pasar mensajes que
el usuario pueda necesitar ver en la siguiente petición. Para lograr esto,
FlashMessenger usa
Zend_Session_Namespace para almacenar mensajes para su
recuperación en una petición futura o en la siguiente. Generalmente es una
buena idea, si planea usar Zend_Session o
Zend_Session_Namespace, inicializar con
Zend_Session::start() en su archivo de arranque
(bootstrap). (Consulte la documentación de
Zend_Session
para más detalles sobre su uso.)
Métodos generales:
setNamespace($namespace='default')se usa para establecer el espacio de nombres en el que se almacenan los mensajes por defecto.getNamespace()se usa para recuperar el nombre del espacio de nombres por defecto. El espacio de nombres por defecto es 'default'.resetNamespace()se usa para restablecer el nombre del espacio de nombres al valor por defecto, 'default'.
Métodos para manipular mensajes establecidos en la petición anterior:
hasMessages($namespace=NULL)se usa para determinar si se han transportado mensajes de una petición anterior mediante el flash messenger. El argumento opcional$namespaceespecifica en qué espacio de nombres buscar. Si se omite el argumento$namespace, se usará el valor devuelto porgetNamespace().getMessages($namespace=NULL)se usa para recuperar los mensajes que se han transportado de una petición anterior mediante el flash messenger. El argumento opcional$namespaceespecifica de qué espacio de nombres extraer. Si se omite el argumento$namespace, se usará el valor devuelto porgetNamespace().getIterator($namespace=NULL)envuelve el valor de retorno degetMessages()en una instancia deArrayObject. Si se omite el argumento$namespace, se usará el valor devuelto porgetNamespace().count($namespace=NULL)devuelve el número de mensajes contenidos en el espacio de nombres especificado. Si se omite el argumento$namespace, se usará el valor devuelto porgetNamespace().clearMessages($namespace=NULL)se usa para borrar todos los mensajes que se han transportado de una petición anterior mediante el flash messenger. El argumento opcional$namespaceespecifica qué espacio de nombres borrar. Si se omite el argumento$namespace, se usará el valor devuelto porgetNamespace().
Métodos para manipular mensajes establecidos en la petición actual:
addMessage($message, $namespace=NULL)se usa para agregar un nuevo mensaje a la petición actual.$messagecontiene el mensaje a agregar, y el argumento opcional$namespaceespecificará el espacio de nombres. Si se omite el argumento$namespace, se usará el valor devuelto porgetNamespace().hasCurrentMessages($namespace=NULL)se usa para determinar si se han agregado mensajes al flash messenger durante la petición actual. El argumento opcional$namespaceespecifica en qué espacio de nombres buscar. Si se omite el argumento$namespace, se usará el valor devuelto porgetNamespace().getCurrentMessages($namespace=NULL)se usa para recuperar los mensajes que se han agregado al flash messenger durante la petición actual. El argumento opcional$namespaceespecifica de qué espacio de nombres extraer. Si se omite el argumento$namespace, se usará el valor devuelto porgetNamespace().clearCurrentMessages($namespace=NULL)se usa para borrar todos los mensajes que se han agregado al flash messenger durante la petición actual. El argumento opcional$namespaceespecifica qué espacio de nombres borrar. Si se omite el argumento$namespace, se usará el valor devuelto porgetNamespace().
El ejemplo de uso a continuación muestra el uso del flash messenger en su
forma más básica. Cuando se llama a la acción /some/my,
esta agrega el mensaje flash "Record Saved!" Una petición posterior a la
acción /some/my-next-request lo recuperará (y por lo
tanto también lo eliminará).
class SomeController extends Zend_Controller_Action
{
/**
* FlashMessenger
*
* @var Zend_Controller_Action_Helper_FlashMessenger
*/
protected $_flashMessenger = null;
public function init()
{
$this->_flashMessenger =
$this->_helper->getHelper('FlashMessenger');
$this->initView();
}
public function myAction()
{
/**
* default method of getting
* Zend_Controller_Action_Helper_FlashMessenger instance
* on-demand
*/
$this->_flashMessenger->addMessage('Record Saved!');
}
public function myNextRequestAction()
{
$this->view->messages = $this->_flashMessenger->getMessages();
$this->render();
}
}
Las respuestas JSON se están convirtiendo rápidamente en la respuesta preferida al tratar con peticiones AJAX que esperan respuestas de conjuntos de datos; JSON se puede analizar (parsear) de inmediato en el lado del cliente, lo que conduce a una ejecución rápida.
El uso es simple: ya sea llamándolo como un método del corredor de
ayudantes, o llamando a uno de los métodos encodeJson()
o sendJson():
direct($data, $sendNow = true, $keepLayouts = false, $encodeData = true)
sendJson($data, $keepLayouts = false, $encodeData = true)
encodeJson($data, $keepLayouts = false, $encodeData = true)
$data: datos a codificar como JSON
$sendNow: bandera para definir si se deben enviar los datos JSON de inmediato. Cuando es true, el ayudante establecerá inmediatamente el cuerpo de la respuesta y saldrá.
$keepLayouts: bandera para definir si se deben habilitar o deshabilitar los layouts. Cuando es false, se deshabilitan todos los layouts. Opcionalmente, esto puede ser un arreglo de opciones para pasar como segundo argumento a
Zend_Json::encode(). Este arreglo de opciones permite habilitar los layouts y codificar usandoZend_Json_Expr.$encodeData: bandera para definir si $data ya está codificado en JSON. Cuando es true, este ayudante no codificará $data a JSON antes de enviarlo.
![]() |
Manteniendo los layouts |
|---|---|
|
Si tiene un layout separado para las respuestas JSON --
quizás para envolver la respuesta JSON en algún tipo de
contexto -- cada método en el ayudante JSON acepta un
argumento opcional $keepLayouts: una bandera para
habilitar o deshabilitar los layouts. Pasar un valor booleano
$this->_helper->json($data, true); Opcionalmente, puede pasar un arreglo como tercer parámetro. Este arreglo puede contener una variedad de opciones, incluyendo la opción keepLayouts:
// Direct helper call
$this->_helper->json($data, true, array('keepLayouts' => true);
// ...or, call a method of the helper
$this->_helper->sendJson($data, array('keepLayouts' => true));
|
![]() |
Habilitar la codificación usando Zend_Json_Expr |
|---|---|
|
$this->_helper->json($data, true, array('enableJsonExprFinder' => true);
Si desea hacer esto, debe pasar un arreglo
como tercer argumento. Esto también le permite combinar otras opciones,
como la opción keepLayouts. Todas esas opciones
se pasan entonces a $this->_helper->json($data, true, array( 'enableJsonExprFinder' => true, 'keepLayouts' => true, )); |
class FooController extends Zend_Controller_Action
{
public function barAction()
{
// do some processing...
// Send the JSON response:
$this->_helper->json($data);
// or...
$this->_helper->json->sendJson($data);
// or retrieve the json:
$json = $this->_helper->json->encodeJson($data);
}
}
El ayudante Redirector le permite usar un objeto
redirector para satisfacer las necesidades de su aplicación de redirigir a
una nueva URL. Proporciona numerosas ventajas sobre el
método _redirect(), como poder preconfigurar el
comportamiento a nivel de sitio en el objeto redirector o usar la interfaz
incorporada gotoSimple($action, $controller, $module, $params)
similar a la de Zend_Controller_Action::_forward().
El Redirector tiene varios métodos que se pueden usar para afectar el comportamiento en la redirección:
setCode()se puede usar para establecer el código de respuesta HTTP a usar durante la redirección.setExit()se puede usar para forzar unexit()tras una redirección. Por defecto esto esTRUE.setGotoSimple()se puede usar para establecer una URL por defecto a usar si no se pasa ninguna agotoSimple(). Usa la API deZend_Controller_Action::_forward():setGotoSimple($action, $controller = null, $module = null, array $params = array())setGotoRoute()se puede usar para establecer una URL basada en una ruta registrada. Pase un arreglo de pares clave/valor y un nombre de ruta, y ensamblará la URL de acuerdo con el tipo y la definición de la ruta.setGotoUrl()se puede usar para establecer una URL por defecto a usar si no se pasa ninguna agotoUrl(). Acepta una única cadena URL.setPrependBase()se puede usar para anteponer la URL base del objeto de petición a una URL especificada consetGotoUrl(),gotoUrl(), ogotoUrlAndExit().setUseAbsoluteUri()se puede usar para forzar al Redirector a usar URIs absolutos al redirigir. Cuando se establece esta opción, usa el valor de$_SERVER['HTTP_HOST'],$_SERVER['SERVER_PORT'], y$_SERVER['HTTPS']para formar una URI completa a la URL especificada por uno de los métodos de redirección. Esta opción está desactivada por defecto, pero puede habilitarse por defecto en versiones posteriores.
Además, hay una variedad de métodos en el redirector para realizar las redirecciones propiamente dichas:
gotoSimple()usasetGotoSimple()(API similar a_forward()) para construir una URL y realizar una redirección.gotoRoute()usasetGotoRoute()(ensamblado de ruta) para construir una URL y realizar una redirección.gotoUrl()usasetGotoUrl()(cadena URL) para construir una URL y realizar una redirección.
Finalmente, puede determinar la URL de redirección
actual en cualquier momento usando getRedirectUrl().
Ejemplo 24.6. Establecer opciones
Este ejemplo sobrescribe varias opciones, incluyendo el establecimiento del código de estado HTTP a usar en la redirección ('303'), sin salir por defecto tras la redirección, y definiendo una URL por defecto a usar al redirigir.
class SomeController extends Zend_Controller_Action
{
/**
* Redirector - defined for code completion
*
* @var Zend_Controller_Action_Helper_Redirector
*/
protected $_redirector = null;
public function init()
{
$this->_redirector = $this->_helper->getHelper('Redirector');
// Set the default options for the redirector
// Since the object is registered in the helper broker, these
// become relevant for all actions from this point forward
$this->_redirector->setCode(303)
->setExit(false)
->setGotoSimple("this-action",
"some-controller");
}
public function myAction()
{
/* do some stuff */
// Redirect to a previously registered URL, and force an exit
// to occur when done:
$this->_redirector->redirectAndExit();
return; // never reached
}
}
Ejemplo 24.7. Uso de los valores por defecto
Este ejemplo asume que se usan los valores por defecto, lo que
significa que cualquier redirección resultará en un
exit() inmediato.
// ALTERNATIVE EXAMPLE
class AlternativeController extends Zend_Controller_Action
{
/**
* Redirector - defined for code completion
*
* @var Zend_Controller_Action_Helper_Redirector
*/
protected $_redirector = null;
public function init()
{
$this->_redirector = $this->_helper->getHelper('Redirector');
}
public function myAction()
{
/* do some stuff */
$this->_redirector
->gotoUrl('/my-controller/my-action/param1/test/param2/test2');
return; // never reached since default is to goto and exit
}
}
Ejemplo 24.8. Uso de la API _forward() de goto()
La API de gotoSimple() imita la de
Zend_Controller_Action::_forward(). La diferencia
principal es que construye una URL a partir de los
parámetros pasados, y usando el formato
:module/:controller/:action/* por defecto del
enrutador por defecto. Luego redirige en lugar de encadenar la acción.
class ForwardController extends Zend_Controller_Action
{
/**
* Redirector - defined for code completion
*
* @var Zend_Controller_Action_Helper_Redirector
*/
protected $_redirector = null;
public function init()
{
$this->_redirector = $this->_helper->getHelper('Redirector');
}
public function myAction()
{
/* do some stuff */
// Redirect to 'my-action' of 'my-controller' in the current
// module, using the params param1 => test and param2 => test2
$this->_redirector->gotoSimple('my-action',
'my-controller',
null,
array('param1' => 'test',
'param2' => 'test2'
)
);
}
}
Ejemplo 24.9. Uso del ensamblado de rutas con gotoRoute()
El siguiente ejemplo usa el método assemble() del
enrutador
para crear una URL basada en un arreglo asociativo de
parámetros pasado. Se asume que se ha registrado la siguiente ruta:
$route = new Zend_Controller_Router_Route(
'blog/:year/:month/:day/:id',
array('controller' => 'archive',
'module' => 'blog',
'action' => 'view')
);
$router->addRoute('blogArchive', $route);
Dado un arreglo con year establecido en 2006, month en 4, day en 24, e
id en 42, entonces construiría la URL
/blog/2006/4/24/42.
class BlogAdminController extends Zend_Controller_Action
{
/**
* Redirector - defined for code completion
*
* @var Zend_Controller_Action_Helper_Redirector
*/
protected $_redirector = null;
public function init()
{
$this->_redirector = $this->_helper->getHelper('Redirector');
}
public function returnAction()
{
/* do some stuff */
// Redirect to blog archive. Builds the following URL:
// /blog/2006/4/24/42
$this->_redirector->gotoRoute(
array('year' => 2006,
'month' => 4,
'day' => 24,
'id' => 42),
'blogArchive'
);
}
}
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 se registrarán automáticamente con el controlador.
Establecer automáticamente las rutas de scripts de vista, ayudantes y filtros basadas en el módulo actual, y asociar automáticamente el nombre del módulo actual como prefijo de clase para las clases de ayudantes y filtros.
Crear un objeto de vista globalmente disponible para todos los controladores y acciones despachados.
Permitir al desarrollador establecer opciones de renderización de vista por defecto para todos los controladores.
Agregar la capacidad de renderizar automáticamente un script de vista sin intervención.
Permitir al desarrollador crear sus propias especificaciones para la ruta base de la vista y para las rutas de scripts de vista.
![]() |
Nota |
|---|---|
Si realiza un |
![]() |
Nota |
|---|---|
|
El ViewRenderer está habilitado por defecto. Puede
deshabilitarlo mediante el parámetro
noViewRenderer del controlador frontal
($front->setParam('noViewRenderer', true);) o
eliminando el ayudante de la pila del corredor de ayudantes
( Si desea modificar la configuración del ViewRenderer antes de despachar el controlador frontal, puede hacerlo de una de dos maneras:
|
En su uso más básico, simplemente instancia el
ViewRenderer y lo pasa al corredor de ayudantes de
acción. La forma más fácil de instanciarlo y registrarlo de una sola vez
es usar el método getStaticHelper() del corredor de
ayudantes:
Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
La primera vez que se instancia un controlador de acción, activará al
ViewRenderer para que instancie un objeto de vista.
Cada vez que se instancia un controlador, se llama al método
init() del ViewRenderer, lo cual
hará que establezca la propiedad view del controlador de acción, y llame
a addScriptPath() con una ruta relativa al módulo
actual; esto se llamará con un prefijo de clase con el nombre del módulo
actual, delimitando efectivamente todas las clases de ayudantes y
filtros que defina para el módulo.
Cada vez que se llama a postDispatch(), este
llamará a render() para la acción actual.
Como ejemplo, considere la siguiente clase:
// A controller class, foo module:
class Foo_BarController extends Zend_Controller_Action
{
// Render bar/index.phtml by default; no action required
public function indexAction()
{
}
// Render bar/populate.phtml with variable 'foo' set to 'bar'.
// Since view object defined at preDispatch(), it's already available.
public function populateAction()
{
$this->view->foo = 'bar';
}
}
...
// in one of your view scripts:
$this->foo(); // call Foo_View_Helper_Foo::foo()
El ViewRenderer también define una serie de accesores para permitir establecer y recuperar opciones de vista:
setView($view)le permite establecer el objeto de vista para el ViewRenderer. Se establece como la propiedad pública de clase$view.setNeverRender($flag = true)se puede usar para deshabilitar o habilitar la renderización automática globalmente, es decir, para todos los controladores. Si se establece enTRUE,postDispatch()no llamará automáticamente arender()en el controlador actual.getNeverRender()recupera el valor actual.setNoRender($flag = true)se puede usar para deshabilitar o habilitar la renderización automática. Si se establece enTRUE,postDispatch()no llamará automáticamente arender()en el controlador actual. Esta configuración se restablece cada vez que se llama apreDispatch()(es decir, necesita establecer esta bandera para cada controlador para el que no desee que ocurra la renderización automática).getNoRender()recupera el valor actual.setNoController($flag = true)se puede usar para indicarle arender()que no busque el script de acción en un subdirectorio con el nombre del controlador (que es el comportamiento por defecto).getNoController()recupera el valor actual.setNeverController($flag = true)es análogo asetNoController(), pero funciona a nivel global -- es decir, no se restablecerá para cada acción despachada.getNeverController()recupera el valor actual.setScriptAction($name)se puede usar para especificar el script de acción a renderizar.$namedebe ser el nombre del script sin el sufijo de archivo (y sin el subdirectorio del controlador, a menos que noController esté activado). Si no se especifica, busca un script de vista con el nombre de la acción en el objeto de petición.getScriptAction()recupera el valor actual.setResponseSegment($name)se puede usar para especificar en qué segmento con nombre del objeto de respuesta renderizar. Si no se especifica, renderiza en el segmento por defecto.getResponseSegment()recupera el valor actual.initView($path, $prefix, $options)se puede llamar para especificar la ruta base de la vista, el prefijo de clase para los scripts de ayudantes y filtros, y las opciones del ViewRenderer. Puede pasar cualquiera de las siguientes banderas: neverRender, noRender, noController, scriptAction, y responseSegment.-
setRender($action = null, $name = null, $noController = false)le permite establecer cualquiera de scriptAction, responseSegment, y noController en una sola pasada.direct()es un alias de este método, lo que le permite llamarlo fácilmente desde su controlador:// Render 'foo' instead of current action script $this->_helper->viewRenderer('foo'); // render form.phtml to the 'html' response segment, without using a // controller view script subdirectory: $this->_helper->viewRenderer('form', 'html', true);![[Note]](images/note.png)
Nota setRender()ydirect()en realidad no renderizan el script de vista, sino que establecen indicaciones quepostDispatch()yrender()usarán para renderizar la vista.
El constructor le permite pasar opcionalmente el objeto de vista y las
opciones del ViewRenderer; acepta las mismas banderas
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 las especificaciones de ruta usadas para determinar la ruta base de vista a agregar al objeto de vista, y la ruta del script de vista a usar al autodeterminar el script de vista a renderizar. Estos métodos toman cada uno uno o más de los siguientes marcadores de posición:
:moduleDir se refiere al directorio base del módulo actual (por convención, el directorio padre del directorio de controladores del módulo).
:module se refiere al nombre del módulo actual.
:controller se refiere al nombre del controlador actual.
:action se refiere al nombre de la acción actual.
:suffix se refiere al sufijo del script de vista (que se puede establecer mediante
setViewSuffix()).
Los métodos para controlar las especificaciones de ruta son:
setViewBasePathSpec($spec)le permite cambiar la especificación de ruta usada para determinar la ruta base a agregar al objeto de vista. La especificación por defecto es:moduleDir/views. Puede recuperar la especificación actual en cualquier momento usandogetViewBasePathSpec().setViewScriptPathSpec($spec)le permite cambiar la especificación de ruta usada para determinar la ruta a un script de vista individual (sin la ruta base del script de vista). La especificación por defecto es:controller/:action.:suffix. Puede recuperar la especificación actual en cualquier momento usandogetViewScriptPathSpec().setViewScriptPathNoControllerSpec($spec)le permite cambiar la especificación de ruta usada para determinar la ruta a un script de vista individual cuando noController está activo (sin la ruta base del script de vista). La especificación por defecto es:action.:suffix. Puede recuperar la especificación actual en cualquier momento usandogetViewScriptPathNoControllerSpec().
Para un control más detallado sobre las especificaciones de ruta, puede usar Zend_Filter_Inflector. Internamente, el ViewRenderer ya utiliza un inflector para realizar los mapeos de ruta. Para interactuar con el inflector -- ya sea para establecer el suyo propio, o para modificar el inflector por defecto -- se pueden usar los siguientes métodos:
-
getInflector()recuperará el inflector. Si aún no existe ninguno en el ViewRenderer, crea uno usando las reglas por defecto.Por defecto, usa referencias de reglas estáticas para el sufijo y el directorio del módulo, así como un objetivo estático; esto permite que varias propiedades del ViewRenderer puedan modificar dinámicamente el inflector.
setInflector($inflector, $reference)le permite establecer un inflector personalizado para usar con el ViewRenderer. Si$referenceesTRUE, establecerá el sufijo y el directorio del módulo como referencias estáticas a propiedades del ViewRenderer, así como el objetivo.
![]() |
Convenciones de búsqueda por defecto |
|---|---|
|
El ViewRenderer realiza cierta normalización de rutas para facilitar las búsquedas de scripts de vista. Las reglas por defecto son las siguientes:
|
Los elementos finales en la API del ViewRenderer son los métodos para determinar realmente las rutas de scripts de vista y renderizar vistas. Estos incluyen:
-
renderScript($script, $name)le permite renderizar un script con una ruta que usted especifique, opcionalmente a una ruta con nombre. Al usar este método, el ViewRenderer no realiza autodeterminación del nombre del script, sino que pasa directamente el argumento$scriptal métodorender()del objeto de vista.![[Note]](images/note.png)
Nota Una vez que la vista se ha renderizado al objeto de respuesta, establece noRender para evitar renderizar accidentalmente el mismo script de vista varias veces.
![[Note]](images/note.png)
Nota Por defecto,
Zend_Controller_Action::renderScript()delega en el métodorenderScript()del ViewRenderer. -
getViewScript($action, $vars)crea la ruta a un script de vista basada en la acción pasada y/o cualquier variable pasada en$vars. Las claves de este arreglo pueden incluir cualquiera de las claves de especificación de ruta ('moduleDir', 'module', 'controller', 'action', y 'suffix'). Se usarán las variables que se pasen; de lo contrario, se usarán valores basados en la petición actual.getViewScript()usará ya sea viewScriptPathSpec o viewScriptPathNoControllerSpec según la configuración de la bandera noController.Los delimitadores de palabras que aparezcan en los nombres de módulo, controlador o acción se reemplazarán con guiones ('-'). Así, si tiene el nombre de controlador 'foo.bar' y la acción 'baz:bat', usando la especificación de ruta por defecto se obtendrá una ruta de script de vista de '
foo-bar/baz-bat.phtml'.![[Note]](images/note.png)
Nota Por defecto,
Zend_Controller_Action::getViewScript()delega en el métodogetViewScript()del ViewRenderer. -
render($action, $name, $noController)verifica primero si se han pasado$nameo$noController, y si es así, establece las banderas apropiadas (responseSegment y noController, respectivamente) en el ViewRenderer. Luego pasa el argumento$action, si lo hay, agetViewScript(). Finalmente, pasa la ruta del script de vista calculada arenderScript().![[Note]](images/note.png)
Nota Tenga en cuenta los efectos secundarios de usar
render(): los valores que pase para el nombre del segmento de respuesta y para la bandera noController persistirán en el objeto. Además, noRender se establecerá una vez completada la renderización.![[Note]](images/note.png)
Nota Por defecto,
Zend_Controller_Action::render()delega en el métodorender()del ViewRenderer. renderBySpec($action, $vars, $name)le permite pasar variables de especificación de ruta para determinar la ruta del script de vista a crear. Pasa$actiony$varsagetScriptPath(), y luego pasa la ruta de script resultante y$namearenderScript().
Ejemplo 24.10. Uso básico
En su forma más básica, simplemente inicializa y registra el ayudante ViewRenderer con el corredor de ayudantes en su bootstrap, y luego establece variables en sus métodos de acción.
// In your bootstrap:
Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
...
// 'foo' module, 'bar' controller:
class Foo_BarController extends Zend_Controller_Action
{
// Render bar/index.phtml by default; no action required
public function indexAction()
{
}
// Render bar/populate.phtml with variable 'foo' set to 'bar'.
// Since view object defined at preDispatch(), it's already available.
public function populateAction()
{
$this->view->foo = 'bar';
}
// Renders nothing as it forwards to another action; the new action
// will perform any rendering
public function bazAction()
{
$this->_forward('index');
}
// Renders nothing as it redirects to another location
public function batAction()
{
$this->_redirect('/index');
}
}
![]() |
Convenciones de nomenclatura: delimitadores de palabras en nombres de controlador y acción |
|---|---|
|
Si el nombre de su controlador o acción está compuesto por varias
palabras, el despachador requiere que estas se separen en la
URL mediante caracteres delimitadores de ruta y de
palabra específicos. El ViewRenderer reemplaza
cualquier delimitador de ruta encontrado en el nombre del
controlador con un delimitador de ruta real ('/'), y cualquier
delimitador de palabra encontrado con un guion ('-') al crear
rutas. Así, una llamada a la acción
Observe que en el segundo ejemplo, el módulo sigue siendo el
módulo por defecto, pero que, debido a la existencia de un
separador de ruta, el controlador recibe el nombre
|
Ejemplo 24.11. Deshabilitar la renderización automática
Para algunas acciones o controladores, es posible que desee
desactivar la renderización automática -- por ejemplo, si desea
emitir un tipo de salida diferente (XML,
JSON, etc), o si simplemente desea no emitir
nada. Tiene dos opciones: desactivar todos los casos de
renderización automática (setNeverRender()), o
simplemente desactivarla para la acción actual
(setNoRender()).
// Baz controller class, bar module:
class Bar_BazController extends Zend_Controller_Action
{
public function fooAction()
{
// Don't auto render this action
$this->_helper->viewRenderer->setNoRender();
}
}
// Bat controller class, bar module:
class Bar_BatController extends Zend_Controller_Action
{
public function preDispatch()
{
// Never auto render this controller's actions
$this->_helper->viewRenderer->setNoRender();
}
}
![]() |
Nota |
|---|---|
En la mayoría de los casos, no tiene sentido desactivar la
renderización automática globalmente (mediante
|
Ejemplo 24.12. Elegir un script de vista diferente
Algunas situaciones requieren que se renderice un script
diferente al que lleva el nombre de la acción. Por ejemplo, si
tiene un controlador con acciones tanto de agregar como de
editar, ambas pueden mostrar la misma vista 'form', aunque con
valores diferentes establecidos. Puede cambiar fácilmente el
nombre del script usado con setScriptAction(),
setRender(), o llamando al ayudante como un
método, lo cual invocará a setRender().
// Bar controller class, foo module:
class Foo_BarController extends Zend_Controller_Action
{
public function addAction()
{
// Render 'bar/form.phtml' instead of 'bar/add.phtml'
$this->_helper->viewRenderer('form');
}
public function editAction()
{
// Render 'bar/form.phtml' instead of 'bar/edit.phtml'
$this->_helper->viewRenderer->setScriptAction('form');
}
public function processAction()
{
// do some validation...
if (!$valid) {
// Render 'bar/form.phtml' instead of 'bar/process.phtml'
$this->_helper->viewRenderer->setRender('form');
return;
}
// otherwise continue processing...
}
}
Ejemplo 24.13. Modificar la vista registrada
¿Qué sucede si necesita modificar el objeto de vista -- por ejemplo, cambiar las rutas de ayudantes, o la codificación? Puede hacerlo modificando el objeto de vista establecido en su controlador, o tomando el objeto de vista del ViewRenderer; ambos son referencias al mismo objeto.
// Bar controller class, foo module:
class Foo_BarController extends Zend_Controller_Action
{
public function preDispatch()
{
// change view encoding
$this->view->setEncoding('UTF-8');
}
public function bazAction()
{
// Get view object and set escape callback to 'htmlspecialchars'
$view = $this->_helper->viewRenderer->view;
$view->setEscape('htmlspecialchars');
}
}
Ejemplo 24.14. Cambiar las especificaciones de ruta
En algunas circunstancias, puede decidir que las especificaciones de ruta por defecto no se ajustan a las necesidades de su sitio. Por ejemplo, es posible que desee tener un único árbol de plantillas al cual dar acceso a sus diseñadores (esto es muy típico al usar Smarty, por ejemplo). En tal caso, es posible que desee codificar de forma fija la especificación de la ruta base de vista, y crear una especificación alternativa para las rutas de los scripts de vista de las acciones en sí.
Para efectos de este ejemplo, supongamos que la ruta base a las
vistas debe ser '/opt/vendor/templates', y
que desea que los scripts de vista se referencien mediante
':moduleDir/:controller/:action.:suffix'; si
se ha establecido la bandera
noController, desea renderizar desde el
nivel superior en lugar de en un subdirectorio
(':action.:suffix'). Finalmente, desea usar
'tpl' como sufijo del nombre de archivo del script de vista.
/**
* In your bootstrap:
*/
// Different view implementation
$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);
Ejemplo 24.15. Renderizar múltiples scripts de vista desde una única acción
A veces, puede necesitar renderizar múltiples scripts de vista
desde una única acción. Esto es muy sencillo -- simplemente
realice múltiples llamadas a render():
class SearchController extends Zend_Controller_Action
{
public function resultsAction()
{
// Assume $this->model is the current model
$this->view->results =
$this->model->find($this->_getParam('query', '');
// render() by default proxies to the ViewRenderer
// Render first the search form and then the results
$this->render('form');
$this->render('results');
}
public function formAction()
{
// do nothing; ViewRenderer autorenders the view script
}
}
Los ayudantes de acción extienden
Zend_Controller_Action_Helper_Abstract, una clase
abstracta que proporciona la interfaz y funcionalidad básicas
requeridas por el corredor de ayudantes. Estas incluyen los
siguientes métodos:
setActionController()se usa para establecer el controlador de acción actual.init(), activado por el corredor de ayudantes en la instanciación, se puede usar para activar la inicialización en el ayudante; esto puede ser útil para restablecer el estado cuando varios controladores usan el mismo ayudante en acciones encadenadas.preDispatch(), se activa antes de una acción despachada.postDispatch()se activa cuando una acción despachada ha terminado -- incluso si un pluginpreDispatch()ha omitido la acción. Principalmente útil para la limpieza.getRequest()recupera el objeto de petición actual.getResponse()recupera el objeto de respuesta actual.getName()recupera el nombre del ayudante. Recupera la porción del nombre de clase que sigue al último carácter de guion bajo, o el nombre completo de la clase en caso contrario. Como ejemplo, si la clase se llamaZend_Controller_Action_Helper_Redirector, devolverá Redirector; una clase llamada FooMessage simplemente se devolverá a sí misma.
Opcionalmente, puede incluir un método direct() en
su clase de ayudante. Si se define, le permite tratar al ayudante
como un método del corredor de ayudantes, con el fin de permitir un
uso fácil y puntual del ayudante. Como ejemplo, el
redirector
define direct() como un alias de
goto(), permitiendo usar el ayudante así:
// Redirect to /blog/view/item/id/42
$this->_helper->redirector('item', 'view', 'blog', array('id' => 42));
Internamente, el método __call() del corredor de
ayudantes busca un ayudante llamado
redirector, luego verifica si ese ayudante tiene
un método direct() definido, y lo invoca con los
argumentos proporcionados.
Una vez que haya creado su propia clase de ayudante, puede proporcionar acceso a ella como se describe en las secciones anteriores.