Zend_Controller_Action es una clase abstracta que puede usar
para implementar Controladores de Acción para su uso con el Controlador
Frontal al construir un sitio web basado en el
patrón Modelo-Vista-Controlador (MVC).
Para usar Zend_Controller_Action, necesitará
heredar de ella en sus clases de controlador de acción reales (o heredar de ella
para crear su propia clase base para controladores de acción). La operación más
básica es heredar de ella, y crear métodos de acción que
correspondan a las distintas acciones que desea que el controlador maneje
para su sitio. El enrutamiento y despacho de Zend_Controller
descubrirá automáticamente cualquier método que termine en 'Action' en su clase como
posibles acciones del controlador.
Por ejemplo, supongamos que su clase se define de la siguiente manera:
class FooController extends Zend_Controller_Action
{
public function barAction()
{
// do something
}
public function bazAction()
{
// do something
}
}
La clase FooController anterior (controlador foo) define dos acciones, bar y baz.
Hay mucho más que se puede lograr además de esto, como acciones de inicialización personalizadas, acciones por defecto a llamar en caso de que no se especifique ninguna acción (o una acción no válida), enlaces (hooks) de pre- y post-despacho, y una variedad de métodos auxiliares. Este capítulo sirve como una visión general de la funcionalidad del controlador de acción
![]() |
Comportamiento por defecto |
|---|---|
|
Por defecto, el controlador frontal habilita el helper de acción ViewRenderer. Este helper se encarga de inyectar el objeto vista en el controlador, así como de renderizar automáticamente las vistas. Puede deshabilitarlo dentro de su controlador de acción mediante uno de los siguientes métodos:
class FooController extends Zend_Controller_Action
{
public function init()
{
// Local to this controller only; affects all actions,
// as loaded in init:
$this->_helper->viewRenderer->setNoRender(true);
// Globally:
$this->_helper->removeHelper('viewRenderer');
// Also globally, but would need to be in conjunction with the
// local version in order to propagate for this controller:
Zend_Controller_Front::getInstance()
->setParam('noViewRenderer', true);
}
}
También puede simplemente deshabilitar el renderizado para una vista individual estableciendo la bandera noRender del ViewRenderer:
class FooController extends Zend_Controller_Action
{
public function barAction()
{
// disable autorendering for this action only:
$this->_helper->viewRenderer->setNoRender();
}
}
Las razones principales para deshabilitar el ViewRenderer son si simplemente no necesita un objeto vista o si no está renderizando mediante scripts de vista (por ejemplo, cuando se usa un controlador de acción para servir protocolos de servicios web como SOAP, XML-RPC, o REST). En la mayoría de los casos, nunca necesitará deshabilitar globalmente el ViewRenderer, solo selectivamente dentro de controladores o acciones individuales. |
Aunque siempre puede sobrescribir el constructor del controlador de acción,
no lo recomendamos. Zend_Controller_Action::__construct()
realiza algunas tareas importantes, como registrar los objetos de petición y
respuesta, así como cualquier argumento de invocación personalizado pasado
desde el controlador frontal. Si debe sobrescribir el constructor,
asegúrese de llamar a parent::__construct($request, $response,
$invokeArgs).
La forma más apropiada de personalizar la instanciación es usar el
método init(), que es llamado como la última tarea de
__construct(). Por ejemplo, si desea conectarse a
una base de datos en la instanciación:
class FooController extends Zend_Controller_Action
{
public function init()
{
$this->db = Zend_Db::factory('Pdo_Mysql', array(
'host' => 'myhost',
'username' => 'user',
'password' => 'XXXXXXX',
'dbname' => 'website'
));
}
}
Zend_Controller_Action especifica dos métodos que pueden
ser llamados para enmarcar una acción solicitada, preDispatch()
y postDispatch(). Estos pueden ser útiles de varias
maneras: verificar la autenticación y las ACL antes de ejecutar una acción
(al llamar a _forward() en
preDispatch(), la acción será omitida), por ejemplo, o
colocar el contenido generado en una plantilla de todo el sitio
(postDispatch()).
![]() |
Uso de init() vs. preDispatch() |
|---|---|
|
En la sección
anterior, presentamos el método
El método
El método
Nota: |
Varios objetos y variables están registrados con el objeto, y cada uno tiene métodos accesores.
Objeto Request:
getRequest()puede utilizarse para recuperar el objeto de petición usado para llamar a la acción.-
Objeto Response:
getResponse()puede utilizarse para recuperar el objeto de respuesta que agrega la respuesta final. Algunas llamadas típicas podrían ser como sigue:$this->getResponse()->setHeader('Content-Type', 'text/xml'); $this->getResponse()->appendBody($content); Argumentos de Invocación: el controlador frontal puede introducir parámetros en el router, el despachador y el controlador de acción. Para recuperarlos, use
getInvokeArg($key); alternativamente, obtenga la lista completa usandogetInvokeArgs().-
Parámetros de la petición: El objeto de petición agrega los parámetros de la petición, como cualquier parámetro
_GETo_POST, o parámetros de usuario especificados en la información de ruta de la URL. Para recuperarlos, use_getParam($key)o_getAllParams(). También puede establecer parámetros de la petición usando_setParam(); esto es útil cuando se reenvía a acciones adicionales.Para comprobar si un parámetro existe o no (útil para ramificaciones lógicas), use
_hasParam($key).![[Note]](images/note.png)
Nota _getParam()puede tomar un segundo argumento opcional que contiene un valor por defecto para usar si el parámetro no está establecido o está vacío. Usarlo elimina la necesidad de llamar a_hasParam()antes de recuperar un valor:// Use default value of 1 if id is not set $id = $this->_getParam('id', 1); // Instead of: if ($this->_hasParam('id') { $id = $this->_getParam('id'); } else { $id = 1; }
![]() |
La integración de vistas por defecto es a través del ViewRenderer |
|---|---|
El contenido de esta sección solo es válido cuando ha deshabilitado explícitamente el ViewRenderer. De lo contrario, puede saltarse esta sección sin problema. |
Zend_Controller_Action proporciona un mecanismo rudimentario y
flexible para la integración de vistas. Dos métodos logran
esto, initView() y render(); el
primer método carga de forma diferida (lazy-load) la propiedad pública $view, y el
segundo renderiza una vista basada en la acción solicitada actual, usando
la jerarquía de directorios para determinar la ruta del script.
initView() inicializa el objeto vista.
render() llama a initView() para
recuperar el objeto vista, pero puede ser inicializado en cualquier momento;
por defecto puebla la propiedad $view con un objeto
Zend_View, pero se puede usar cualquier clase que implemente
Zend_View_Interface. Si
$view ya está inicializada, simplemente devuelve
esa propiedad.
La implementación por defecto asume la siguiente estructura de directorios:
applicationOrModule/
controllers/
IndexController.php
views/
scripts/
index/
index.phtml
helpers/
filters/
En otras palabras, se asume que los scripts de vista están en el
subdirectorio /views/scripts/, y se asume que el
subdirectorio /views/ contiene funcionalidad hermana
(helpers, filtros). Al determinar el nombre y la ruta del script de vista, el
directorio /views/scripts/ se usará como ruta base, con
directorios nombrados según los controladores individuales proporcionando una
jerarquía de scripts de vista.
render() tiene la siguiente firma:
string render(string $action = null,
string $name = null,
bool $noController = false);
render() renderiza un script de vista. Si no se
pasan argumentos, asume que el script solicitado es
[controller]/[action].phtml (donde
.phtml es el valor de la propiedad $viewSuffix).
Pasar un valor para $action renderizará
esa plantilla en el subdirectorio /[controller]/. Para
omitir el uso del subdirectorio /[controller]/, pase
un valor TRUE para $noController. Finalmente,
las plantillas se renderizan en el objeto respuesta; si desea renderizar en
un segmento
con nombre específico en el objeto respuesta, pase un valor para
$name.
![]() |
Nota |
|---|---|
Dado que los nombres de controlador y acción pueden contener caracteres
delimitadores de palabras como '_', '.', y '-', |
Algunos ejemplos:
class MyController extends Zend_Controller_Action
{
public function fooAction()
{
// Renders my/foo.phtml
$this->render();
// Renders my/bar.phtml
$this->render('bar');
// Renders baz.phtml
$this->render('baz', null, true);
// Renders my/login.phtml to the 'form' segment of the
// response object
$this->render('login', 'form');
// Renders site.phtml to the 'page' segment of the response
// object; does not use the 'my/' subirectory
$this->render('site', 'page', true);
}
public function bazBatAction()
{
// Renders my/baz-bat.phtml
$this->render();
}
}
Además de los accesores y los métodos de integración de vistas,
Zend_Controller_Action tiene varios métodos utilitarios para
realizar tareas comunes desde dentro de sus métodos de acción (o desde
pre- y post-despacho).
_forward($action, $controller = null, $module = null, array $params = null): realiza otra acción. Si se llama enpreDispatch(), la acción actualmente solicitada será omitida en favor de la nueva. De lo contrario, después de que la acción actual sea procesada, la acción solicitada en_forward()será ejecutada.-
_redirect($url, array $options = array()): redirige a otra ubicación. Este método toma una URL y un conjunto opcional de opciones. Por defecto, realiza una redirección HTTP 302.Las opciones pueden incluir una o más de las siguientes:
-
exit: si se debe salir inmediatamente o no. Si se solicita, cerrará limpiamente cualquier sesión abierta y realizará la redirección.
Puede establecer esta opción globalmente dentro del controlador usando el accesor
setRedirectExit(). -
prependBase: si se debe anteponer o no la URL base registrada con el objeto de petición a la URL proporcionada.
Puede establecer esta opción globalmente dentro del controlador usando el accesor
setRedirectPrependBase(). -
code: qué código HTTP utilizar en la redirección. Por defecto, se utiliza un HTTP 302; se puede usar cualquier código entre 301 y 306.
Puede establecer esta opción globalmente dentro del controlador usando el accesor
setRedirectCode().
-
Por diseño, Zend_Controller_Action debe heredarse
para crear un controlador de acción. Como mínimo, necesitará
definir métodos de acción que el controlador pueda llamar.
Además de crear funcionalidad útil para sus aplicaciones web, también
puede encontrar que está repitiendo gran parte de la misma configuración o
métodos utilitarios en sus distintos controladores; si es así, crear una
clase de controlador base común que herede de
Zend_Controller_Action podría resolver dicha redundancia.
Ejemplo 24.1. Manejo de Acciones Inexistentes
Si se hace una petición a un controlador que incluye un método de
acción no definido, se invocará Zend_Controller_Action::__call().
__call() es, por supuesto,
el método mágico de PHP para la sobrecarga de métodos.
Por defecto, este método lanza una
Zend_Controller_Action_Exception indicando que el
método solicitado no se encontró en el controlador. Si el método
solicitado termina en 'Action', se asume que se solicitó una acción y
no existe; dichos errores resultan en una excepción
con código 404. Todos los demás métodos resultan en una excepción
con código 500. Esto le permite diferenciar fácilmente
entre página no encontrada y errores de aplicación en su manejador
de errores.
Debería sobrescribir esta funcionalidad si desea realizar otras operaciones. Por ejemplo, si desea mostrar un mensaje de error, podría escribir algo como esto:
class MyController extends Zend_Controller_Action
{
public function __call($method, $args)
{
if ('Action' == substr($method, -6)) {
// If the action method was not found, render the error
// template
return $this->render('error');
}
// all other methods throw an exception
throw new Exception('Invalid method "'
. $method
. '" called',
500);
}
}
Otra posibilidad es que quiera reenviar a una página de controlador por defecto:
class MyController extends Zend_Controller_Action
{
public function indexAction()
{
$this->render();
}
public function __call($method, $args)
{
if ('Action' == substr($method, -6)) {
// If the action method was not found, forward to the
// index action
return $this->_forward('index');
}
// all other methods throw an exception
throw new Exception('Invalid method "'
. $method
. '" called',
500);
}
}
Además de sobrescribir __call(), cada uno de los
métodos de inicialización, utilitarios, accesores, vista y de enlace de despacho
mencionados anteriormente en este capítulo pueden ser sobrescritos para
personalizar sus controladores. Como ejemplo, si está almacenando su
objeto vista en un registro, podría querer modificar su
método initView() con un código similar al siguiente:
abstract class My_Base_Controller extends Zend_Controller_Action
{
public function initView()
{
if (null === $this->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;
}
}
Esperamos que, a partir de la información de este capítulo, pueda ver la flexibilidad de este componente en particular y cómo puede adaptarlo a las necesidades de su aplicación o sitio.