Controladores de AcciónIntroducciónZend_Controller_Action es una clase abstracta
que puede utilizar para implementar controladores de acción (Action
Controllers) para usar con el Front Controller al crear un un sitio
basado en el patrón Modelo-Vista-Controlador (
MVC ). Para usar Zend_Controller_Action ,
necesitará hacerla una subclase en sus clases actuales de
controladores de acción (o hacerla una subclase para crear su propia
clase base de acción de controladores). La operación más elemental
es hacerla una subclase, y crear métodos de acción que corresponden
a las diversas acciones que desee que el contralor maneje para su
sitio. El manejo del ruteo y envío de
Zend_Controller descubrirá por sí mismo
cualquier método que termine en 'Action' en su clase, como posibles
acciones del controlador. Por ejemplo, digamos que su clase se define como sigue: La clase de arriba FooController (el
controlador foo ) define dos acciones,
bar y baz . Se pueden lograr muchas cosas más, tales como personalizar la
inicialización de acciones, las acciones a llamar por defecto no
deberían especificar ninguna acción (o una acción inválida), ganchos
de pre y post despacho, y una variedad de métodos ayudantes. Este
capítulo sirve como panorama de la funcionalidad del controlador de
acciones. Comportamiento por Defecto Por defecto, el front
controller habilita al ayudante de acción ViewRenderer . Este ayudante toma a su cargo la
inyección del objeto "view" en el contralor, así como
compatibilizar automáticamente las vistas. Usted podrá
desactivarlo dentro de su contralor de acción por uno de los
métodos siguientes: _helper->viewRenderer->setNoRender(true);
// Globalmente:
$this->_helper->removeHelper('viewRenderer');
// También globalmente, pero tendría que ser en conjunción con la
// versión local con el fin de propagarlo para este controlador:
Zend_Controller_Front::getInstance()
->setParam('noViewRenderer', true);
}
}
]]>initView() ,
getViewScript() ,
render() , y
renderScript() cada proxy al
ViewRenderer a menos que el ayudante no
esté como ayudante intermediario o no se haya establecido el
flag de noViewRenderer . También puede simplemente desactivarse para una prestación
individual ajustando el flag noRender de
ViewRenderer : _helper->viewRenderer->setNoRender();
}
}
]]> Las principales razones para desactivar
ViewRenderer son si usted simplemente
no necesita una objeto "view" o si no está mostrándolos via view
scripts (por ejemplo, cuando se utiliza un controlador de acción
para alimentar a los protocolos de un servicio web como
SOAP , XML-RPC , o
REST ). En muchos casos, nunca necesitará
desactivar a ViewRenderer globalmente, sólo
selectivamente dentro de los distintos controladores o acciones.
Inicialización de Objectos Si bien siempre puede anular el contolador de acción del
constructor, no lo recomendamos.
Zend_Controller_Action::__construct()
realiza algunas tareas importantes, tales como registrar los objetos
de solicitud y respuesta, así como los argumentos de cualquier
invocación personalizada pasados desde el front controller. Si debe
anular el constructor, asegúrese de llamar a
parent::__construct($request, $response,
$invokeArgs) . La manera más apropiada de personalizar la instanciación es
utilizar el método init() , el cual es
llamado como la última tarea de
__construct() . Por ejemplo, si se
quiere conectar a una base de datos en la instanciación: db = Zend_Db::factory('Pdo_Mysql', array(
'host' => 'myhost',
'username' => 'user',
'password' => 'XXXXXXX',
'dbname' => 'website'
));
}
}
]]>Ganchos de Pre- and Post-DespachoZend_Controller_Action especifica dos métodos
que pueden ser llamados para marcar una solicitud de acción,
preDispatch() y
postDispatch() . Estas pueden ser
útiles de varias maneras: verificar la autenticación y
ACL s antes de ejecutar una acción (llamando
a _forward() en
preDispatch() , se saltará la acción),
por ejemplo, o colocando contenido generado en una plantilla general
del sitio ( postDispatch() ). Usage of init() vs. preDispatch() In the previous section , we introduced the
init() method, and in this section,
the preDispatch() method. What is the
difference between them, and what actions would you take in
each? The init() method is primarily
intended for extending the constructor. Typically, your
constructor should simply set object state, and not perform much
logic. This might include initializing resources used in the
controller (such as models, configuration objects, etc.), or
assigning values retrieved from the front controller, bootstrap,
or a registry. The preDispatch() method can also be
used to set object or environmental (e.g., view, action helper,
etc.) state, but its primary purpose is to make decisions about
whether or not the requested action should be dispatched. If
not, you should then _forward() to
another action, or throw an exception. Note: _forward() actually will not
work correctly when executed from
init() , which is a formalization
of the intentions of the two methods. Accessors (Accededores) Con el objeto, se registran una serie de objetos y variables, y
cada uno tiene métodos de acceso. Objecto Requerimiento :
getRequest() puede ser
utilizado para recuperar el objeto solicitud utilizado para
llamar a la acción. Objecto Respuesta :
getResponse() puede ser
utilizado para recuperar el objeto respuesta agregando la
respuesta final. Algunas llamadas típicas podrían ser: getResponse()->setHeader('Content-Type', 'text/xml');
$this->getResponse()->appendBody($content);
]]>Argumentos de Invocación : el front
controller puede empujar parámetros al router, al
despachador, y al controlador de acción. Para recuperarlos,
use getInvokeArg($key) ; por otra
parte, se puede traer toda la lista utilizando
getInvokeArgs() . Parámetros de Requerimientos : La
objeto solicitud agrega parámetros de solicitud, como
cualquiera de los parámetros _GET o
_POST , o parámetros del usuario
especificados en la información del path de la
URL . Para recuperarlos, use
_getParam($key) o
_getAllParams() . También se
pueden establecer parámetros de solicitud usando
_setParam() ; lo que es útil
cuando se reenvían a acciones adicionales. Para probar si un parámetro existe o no (muy útil para
bifurcaciones lógicas), use
_hasParam($key) . _getParam() puede tomar
opcionalmente un segundo argumento que contiene un valor
por defecto a utilizar si el parámetro no está
establecido o está vacío. Usándolo elimina la necesidad
de llamar previamente a
_hasParam() para recuperar
un valor: _getParam('id', 1);
// En lugar de:
if ($this->_hasParam('id') {
$id = $this->_getParam('id');
} else {
$id = 1;
}
]]>Integración de VistasIntegración de la Vista por Defecto via ViewRenderer El contenido de esta sección sólo es válida cuando usted
tiene explícitamente deshabilitado a ViewRenderer . De lo contrario, puede saltarse esta
sección. Zend_Controller_Action proporciona un
mecanismo rudimentario y flexible para ver la integración. Hay dos
métodos para lograrlo, initView() y
render() ; el anterior método
$view carga la propiedad pública, y este
último muestra una vista en base a la acción requerida actual,
utilizando la jerarquía del directorio para determinar el path del
script. Inicialización de la VistainitView() inicializa el objeto vista.
render() llama a
initView() con el fin de recuperar
el objeto vista, pero puede ser iniciada en cualquier momento;
por defecto introduce información a la propiedad de
$view con un objeto
Zend_View , pero se puede usar
cualquier clase que implemente
Zend_View_Interface . Si
$view ya ha sido inicializada,
simplemente devuelve esa propiedad. La implementación por defecto hace la siguiente hipótesis de
la estructura del directorio: En otras palabras, los scripts de vista se supone están en el
subdirectorio /views/scripts/ , y en el
subdirectorio /views/ se supone que
contiene funcionalidades hermanas (ayudantes, filtros). Al
determinar el nombre y el path del script, el directorio
views/scripts/ será utilizado como el
path base, con directorios nombrados después que los
controladores individuales proporcionen una jerarquía a los
scripts de vista. Suministrando las Vistasrender() tiene la siguiente firma: render() suministra un script de vista.
Si no se pasan argumentos, se supone que el script requerido es
[controller]/[action].phtml (donde
.phtml es el valor de la propiedad
$viewSuffix ). Pasándole un valor a
$action suministrará esa plantilla en al
subdirectorio /[controller]/ . Para anular
el subdirectorio /[controller]/ ponga un
valor TRUE en
$noController . Por último, las
plantillas son suministradas en el objeto respuesta; si desea
suministrar a un determinado named
segment en el objeto respuesta, pase un valor a
$name . Dado que el controlador y los nombres de acción pueden
contener caracteres delimitadores como '_', '.', y '-',
render() los normaliza a '-'
para determinar el nombre del script. Internamente, utiliza
los delimitadores de palabra y de path del despachador para
hacer esta normalización. Así, una solicitud a
/foo.bar/baz-bat suministrará el
script foo-bar/baz-bat.phtml . Si su
método de acción contiene camelCasing, recuerde que esto se
traducirá en palabras separadas por '-' al determinar el
nombre del archivo del script de vista. Algunos ejemplos: render();
// Suministra my/bar.phtml
$this->render('bar');
// Suministra baz.phtml
$this->render('baz', null, true);
// Suministra my/login.phtml al segmento 'form' del
// objeto respuesta
$this->render('login', 'form');
// Suministra site.phtml al segmento 'page' del objeto
// respuesta; no usa el subdirectorio 'my/'
$this->render('site', 'page', true);
}
public function bazBatAction()
{
// Suministra my/baz-bat.phtml
$this->render();
}
}
]]>Métodos Utilitarios Además de los accesadores y de los métodos de integración de
vistas, Zend_Controller_Action tiene varios
métodos utilitarios para realizar tareas comunes dentro de sus
métodos de acción (o de pre- y post-dispatch). _forward($action, $controller = null, $module =
null, array $params = null) : realiza otra
acción. Si es llamado en
preDispatch() , la acción
actualmente requerida se saltará en favor de la nueva. De lo
contrario, después de procesar la acción actual, se
ejecutará la acción solicitada en _forward(). _redirect($url, array $options =
array()) : redireccionar a otro lugar. Este
método toma una URL y un conjunto de
opciones. Por defecto, realiza una redirección
HTTP 302. Las opciones pueden incluir uno o más de los siguientes: exit: ya sea para salir
inmediatamente o no. Si así lo solicita, limpiamente
cerrará cualquier sesión abierta y realizará la
redirección. Puede configurar esta opción globalmente en el
controlador utilizando el accesador
setRedirectExit() .
prependBase: ya sea
anteponiendo o no la base URL
registrada con el objeto solicitud a la
URL provista. Puede configurar esta opción globalmente en el
controlador utilizando el accesador
setRedirectPrependBase()
. code: qué código
HTTP utilizar en la
redirección. Por defecto, se utiliza un
HTTP 302; se puede utilizar
cualquier código entre 301 y 306. Puede configurar esta opción globalmente en el
controlador utilizando el accesador
setRedirectCode() .
Controladores de Acción y haciendo Subclases Por diseño, Zend_Controller_Action debe
ser "subclaseada" a fin de crear un controlador de acción. Como
mínimo, necesitará definir los métodos de acción que podrá llamar el
controlador. Además de crear una funcionalidad útil para su aplicaciones web,
también puede encontrar que está repitiendo demasiado los mismos
setups o métodos utilitarios en sus diferentes controladores; si así
fuera, creando una clase base común del controlador que extienda
Zend_Controller_Action puede resolver
esta redundacia. Manejando Acciones No Existentes Si hay una solicitud a un controlador que incluye un método
de acción no definido, se invocará a
Zend_Controller_Action::__call() .
__call() es, por supuesto, el
método mágico de PHP para la sobrecarga del
método. Por defecto, este método lanza un
Zend_Controller_Action_Exception
indicando que el método no se encuentró en el controlador. Si el
método requerido termina en 'Action', la suposición es que una
acción fue solicitada y no existe; tales errores resultan en una
excepción con un código 404. Todos los demás métodos resultan en
una excepción con un código 500. Esto le permite diferenciar
fácilmente entre una página no encontrada y errores de
aplicación con su manejador de errores. Usted debe anular esta funcionalidad si desea realizar otras
operaciones. Por ejemplo, si desea mostrar un mensaje de error,
usted podría escribir algo como esto: render('error');
}
// todos los otros métodos lanzan una excepción
throw new Exception('Se ha llamado al método "'
. $method
. '" que es inválido',
500);
}
}
]]> Otra posibilidad es que puede querer avanzar a un controlador
de página por defecto: render();
}
public function __call($method, $args)
{
if ('Action' == substr($method, -6)) {
// Si no se encontró el método de acción, avance a la
// acción index
return $this->_forward('index');
}
// todos los otros métodos lanzan una excepción
throw new Exception('Se ha llamado al método "'
. $method
. '" que es inválido',
500);
}
}
]]> Además de sobrecargar __call() , cada
uno de los métodos gancho de inicialización, utilidad, accesador,
vista, y despacho mencionados anteriormente en este capítulo pueden
ser anulados a fin de personalizar sus controladores. Como ejemplo,
si está almacenando su objeto vista en un registro, quizás desee
modificar su método initView() con código
parecido al siguiente: view) {
if (Zend_Registry::isRegistered('view')) {
$this->view = Zend_Registry::get('view');
} else {
$this->view = new Zend_View();
$this->view->setBasePath(dirname(__FILE__) . '/../views');
}
}
return $this->view;
}
}
]]> Es de esperar, que de la información en este capítulo, usted
puede ver la flexibilidad de este componente en particular y cómo
puede darle forma a su aplicaciones o a las necesidades de su sitio
web.