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.