1 <?xml version="1.0" encoding="UTF-8"?>
2 <!-- EN-Revision: 17175 -->
4 <sect1 id="zend.controller.front">
5 <title>El Front Controller</title>
7 <sect2 id="zend.controller.front.overview">
8 <title>Introducción</title>
11 <classname>Zend_Controller_Front</classname> implementa un <ulink
12 url="http://www.martinfowler.com/eaaCatalog/frontController.html"
13 >Front Controller pattern</ulink> usado en aplicaciones <ulink
14 url="http://en.wikipedia.org/wiki/Model-view-controller"
15 >Model-View-Controller (MVC)</ulink> . Su propósito es
16 inicializar el entorno de la solicitud, rutear la solicitud
17 entrante, y luego hacer un envío de cualquier de las acciones
18 descubiertas; le agrega las respuestas y las regresa cuando se
19 completa el proceso. </para>
22 <classname>Zend_Controller_Front</classname> también implementa el
23 <ulink url="http://en.wikipedia.org/wiki/Singleton_pattern"
24 >Singleton pattern</ulink> , significando que solo una única
25 instancia de él puede estar disponible en cualquier momento dado.
26 Esto le permite actuar también como un registro en el que los demás
27 objetos pueden extraer del proceso dispatch. </para>
30 <classname>Zend_Controller_Front</classname> registra un <link
31 linkend="zend.controller.plugins">plugin broker</link> consigo
32 mismo, permitiendo que diversos eventos que dispara sean observados
33 por plugins. En muchos casos, esto da el desarrollador la
34 oportunidad de adaptar el proceso de dispatch al sitio sin la
35 necesidad de ampliar el Front Controller para añadir funcionalidad. </para>
37 <para> Como mínimo, el front controller necesita una o más paths a
38 directorios que contengan <link linkend="zend.controller.action">
39 action controllers</link> a fin de hacer su trabajo. Una
40 variedad de métodos también pueden ser invocados para seguir
41 adaptando el medio ambiente del front controller y ese a sus helper
45 <title>Comportamiento por Defecto</title>
46 <para> Por defecto, el front controller carga el <link
47 linkend="zend.controller.plugins.standard.errorhandler"
48 >ErrorHandler</link> plugin, así como al <link
49 linkend="zend.controller.actionhelpers.viewrenderer"
50 >ViewRenderer</link> action helper plugin. Estos son para
51 simplificar el manejo de errores y el view renderering en sus
52 controladores, respectivamente. </para>
54 <para> Para deshabilitar el <emphasis>ErrorHandler</emphasis> ,
55 ejecutar lo siguiente en cualquier momento antes de llamar a
56 <methodname>dispatch()</methodname> : </para>
58 <programlisting language="php"><![CDATA[
59 // Deshabilitar el ErrorHandler plugin:
60 $front->setParam('noErrorHandler', true);
63 <para> Para deshabilitar el <emphasis>ViewRenderer</emphasis> , haga
64 lo siguiente antes de llamar a
65 <methodname>dispatch()</methodname> : </para>
67 <programlisting language="php"><![CDATA[
68 // Deshabilitar el ViewRenderer helper:
69 $front->setParam('noViewRenderer', true);
74 <sect2 id="zend.controller.front.methods.primary">
75 <title>Métodos Básicos</title>
77 <para>El front controller tiene varios accessors para establecer su
78 medio ambiente. Sin embargo, hay tres métodos básicos clave para la
79 funcionalidad del front controller:</para>
81 <sect3 id="zend.controller.front.methods.primary.getinstance">
82 <title>getInstance()</title>
85 <methodname>getInstance()</methodname> se utiliza para recuperar
86 una instancia del front controller. Como el front controller
87 implementa un patrón Singleton, este también es el único medio
88 posible para instanciar un objeto front controller. </para>
90 <programlisting language="php"><![CDATA[
91 $front = Zend_Controller_Front::getInstance();
95 <sect3 id="zend.controller.front.methods.primary.setcontrollerdirectory">
96 <title>setControllerDirectory() y addControllerDirectory</title>
99 <methodname>setControllerDirectory()</methodname> se usa para
100 decirle a <link linkend="zend.controller.dispatcher">el
101 dispatcher</link> dónde buscar para los archivos de clase
102 <link linkend="zend.controller.action">action
103 controller</link> . Acepta bien un único path o un array
104 asociativo de pares módulo/path. </para>
106 <para>Como algunos ejemplos:</para>
108 <programlisting language="php"><![CDATA[
109 // Establer el directorio de controladores por defecto:
110 $front->setControllerDirectory('../application/controllers');
112 // Establecer varios directorios módulos a la vez:
113 $front->setControllerDirectory(array(
114 'default' => '../application/controllers',
115 'blog' => '../modules/blog/controllers',
116 'news' => '../modules/news/controllers',
119 // Agregar un directorio de módulos 'foo':
120 $front->addControllerDirectory('../modules/foo/controllers', 'foo');
124 <para> Si usa <methodname>addControllerDirectory()</methodname>
125 sin un nombre de módulo, este establecerá el directorio
126 <emphasis>default</emphasis> para el módulo --
127 sobreescribiéndolo si ya existe. </para>
130 <para> Puede conseguir la configuración actual para el directorio
131 del controlador utilizando
132 <methodname>getControllerDirectory()</methodname> ; este
133 devolverá un array de pares módulo y directorio. </para>
136 <sect3 id="zend.controller.front.methods.primary.addmoduledirectory">
137 <title>addModuleDirectory() y getModuleDirectory()</title>
139 <para> Uno de los aspectos del front controller es que puede <link
140 linkend="zend.controller.modular"> definir una estructura
141 modular de directorio</link> para crear componentes
142 standalone; estos son llamados "módulos". </para>
144 <para> Cada módulo debe estar en su propio directorio y ser un
145 espejo de la estructura del directorio del módulo por defecto --
146 es decir, que debería tener como mínimo un subdirectorio de
147 <filename>/controllers/</filename> , y típicamente un
148 subdirectorio de <filename>/views/</filename> y otros
149 subdirectorios de aplicaciones. </para>
152 <methodname>addModuleDirectory()</methodname> permite pasar el
153 nombre de un directorio que contiene uno o más directorios de
154 módulos. A continuación lo analiza y los añade como directorios
155 de controladores al front controller. </para>
157 <para> Después, si quiere determinar el path a un determinado módulo
158 o al módulo actual, puede llamar a
159 <methodname>getModuleDirectory()</methodname> ,
160 opcionalmente puede pasar un nombre de módulo para conseguir el
161 directorio de ese módulo específico. </para>
164 <sect3 id="zend.controller.front.methods.primary.dispatch">
165 <title>dispatch()</title>
168 <methodname>dispatch(Zend_Controller_Request_Abstract $request =
169 null, Zend_Controller_Response_Abstract $response =
170 null)</methodname> hace el trabajo pesado del front
171 controller. Puede opcionalmente tomar un <link
172 linkend="zend.controller.request">request object</link> y/o
173 un <link linkend="zend.controller.response">response
174 object</link> , permitiendo al desarrollador pasar objetos
175 peronalizados para cada uno. </para>
177 <para> Si no se pasa ningun objeto solicitud o respuesta,
178 <methodname>dispatch()</methodname> comprobará por objetos
179 previamente registrados y utilizará esos o instanciará versiones
180 por defecto a utilizar en su proceso (en ambos casos, el sabor
181 de <acronym>HTTP</acronym> será utilizado por defecto). </para>
183 <para> Similarmente, <methodname>dispatch()</methodname> comprueba
184 los objetos registrados <link linkend="zend.controller.router"
185 >router</link> y <link linkend="zend.controller.dispatcher"
186 >dispatcher</link> , instanciando las versiones por defecto
187 de cada uno si ninguno de ellos se encuentra. </para>
189 <para>El proceso de dispatch tiene tres eventos distintos:</para>
196 <para>Dispatching</para>
199 <para>Response</para>
203 <para> El routing se lleva a cabo exactamente una vez, utilizando
204 los valores del objeto solicitud cuando se llama a
205 <methodname>dispatch()</methodname> . El dispatching se
206 lleva a cabo en un bucle; una solicitud puede indicar, bien
207 múltiples acciones de dispatch, o el controlador o un plugin
208 pueden restablecer el objeto solicitud para forzar medidas
209 adicionales para dispatch. Cuando todo está hecho, el front
210 controller devuelve una respuesta. </para>
213 <sect3 id="zend.controller.front.methods.primary.run">
217 <methodname>Zend_Controller_Front::run($path)</methodname> es un
218 método estático que toma simplemente un path a un directorio que
219 contiene controladores. Obtiene una instancia del front
220 controller (via <link
221 linkend="zend.controller.front.methods.primary.getinstance"
222 >getInstance()</link> , registra el path provisto via <link
223 linkend="zend.controller.front.methods.primary.setcontrollerdirectory"
224 >setControllerDirectory()</link> , y finalmente <link
225 linkend="zend.controller.front.methods.primary.dispatch"
226 >dispatches</link> . </para>
228 <para> Básicamente, <methodname>run()</methodname> es un método
229 conveniente que pueden utilizarse para setups de sitios que no
230 requieran la personalización del medio ambiente del front
233 <programlisting language="php"><![CDATA[
234 // Instanciar el front controller, establecer el directorio de controladores,
235 // y hacer el dispatch fácilmente en en un solo paso:
236 Zend_Controller_Front::run('../application/controllers');
241 <sect2 id="zend.controller.front.methods.environment">
242 <title>Métodos Accessor Ambientales</title>
244 <para>Además de los métodos enumerados anteriormente, hay una serie de
245 métodos accessor que pueden utilizarse para afectar el entorno del
246 front controller -- y por lo tanto el ambiente de las clases a las
247 cuales delega el front controller.</para>
252 <methodname>resetInstance()</methodname> puede ser utilizada
253 para borrar todos los settings actuales. Su objetivo
254 principal es para testing, pero también puede ser utilizada
255 para instancias donde desee encadenar múltiples front
261 <methodname>(set|get)DefaultControllerName()</methodname>
262 permite especificar un nombre diferente para usar en el
263 controlador por defecto (en caso coontrario, se usa 'index')
264 y recuperar el valor actual. Delegan a <link
265 linkend="zend.controller.dispatcher">el
266 dispatcher</link> . </para>
271 <methodname>setDefaultAction()</methodname> y
272 <methodname>getDefaultAction()</methodname> le deja
273 especificar un nombre diferente a utilizar para la acción
274 predeterminada (en caso coontrario, se usa 'index') y
275 recuperar el valor actual. Delegan a <link
276 linkend="zend.controller.dispatcher">el
277 dispatcher</link> . </para>
282 <methodname>setRequest()</methodname> y
283 <methodname>getRequest()</methodname> le permite
284 especificar la clase u objeto <link
285 linkend="zend.controller.request">el request</link> a
286 usar durante el proceso de dispatch y recuperar el objeto
287 actual. Al setear el objeto solicitud, puede pasarlo en un
288 nombre de clase de solicitud, en cuyo caso el método va a
289 cargar el archivo clase y lo instanciará. </para>
294 <methodname>setRouter()</methodname>
295 <methodname>getRouter()</methodname> le permite especificar
296 la clase u objeto <link linkend="zend.controller.router">el
297 router</link> a usar durante el proceso de dispatch y
298 recuperar el objeto actual. Al setear el objeto router,
299 puede pasarlo en un nombre de clase de router, en cuyo caso
300 el método va a cargar el archivo clase y lo instanciará. </para>
302 <para>Al recuperar el objeto router, en primer lugar comprueba
303 para ver si hay alguno presente, y si no, instancia al
304 router por defecto(reescribe el router). </para>
309 <methodname>setBaseUrl()</methodname> y
310 <methodname>getBaseUrl()</methodname> le permite
312 linkend="zend.controller.request.http.baseurl">la URL
313 base</link> de la cual tirar cuando se rutean peticiones
314 y recuperar el valor actual. El valor se provee al objeto
315 solicitud justo antes de rutear. </para>
320 <methodname>setDispatcher()</methodname> y
321 <methodname>getDispatcher()</methodname> le permite
322 especificar la clase u objeto <link
323 linkend="zend.controller.dispatcher">el
324 dispatcher</link> a usar durante el proceso de dispatch
325 y recuperar el objeto actual. Al setear el objeto dispatch,
326 puede pasarlo en un nombre de clase de dispatcher, en cuyo
327 caso el método va a cargar el archivo clase y lo
330 <para>Al recuperar el objeto dispatch, en primer lugar comprueba
331 para ver si hay alguno presente, y si no, instancia al
332 dispatcher por defecto.</para>
337 <methodname>setResponse()</methodname> y
338 <methodname>getResponse()</methodname> le permite
339 especificar la clase u objeto <link
340 linkend="zend.controller.response">response</link> a
341 usar durante el proceso de dispatch y recuperar el objeto
342 actual. Al setear el objeto response, puede pasarlo en un
343 nombre de clase de response, en cuyo caso el método va a
344 cargar el archivo clase y lo instanciará. </para>
349 <methodname>registerPlugin(Zend_Controller_Plugin_Abstract
350 $plugin, $stackIndex = null)</methodname> le permite
351 registrar <link linkend="zend.controller.plugins">plugin
352 objects</link> . Opcionalmente, setting
353 <varname>$stackIndex</varname> , puede controlar el
354 orden en que se ejecutarán los plugins. </para>
359 <methodname>unregisterPlugin($plugin)</methodname> le
360 permite desregistrar <link linkend="zend.controller.plugins"
361 >plugin objects</link> . <varname>$plugin</varname>
362 puede ser tanto un objeto plugin o un string que denota la
363 clase de plugin a desregistrar. </para>
368 <methodname>throwExceptions($flag)</methodname> se utiliza
369 para activar o desactivar la capacidad de arrojar
370 excepciones durante el proceso de dispatch. Por defecto, las
371 excepciones son capturadas y colocadas en el <link
372 linkend="zend.controller.response">objeto response
374 <methodname>throwExceptions()</methodname> se anulará
375 este comportamiento. </para>
377 <para> Para más información, lea <xref
378 linkend="zend.controller.exceptions"/> MVC
384 <methodname>returnResponse($flag)</methodname> se usa para
385 decirle al front controller cuando regresar la respuesta (
386 <constant>TRUE</constant> ) desde
387 <methodname>dispatch()</methodname> , o si la respuesta
388 debe ser emitida automáticamente (
389 <constant>FALSE</constant> ). Por defecto, la respuesta
390 es automáticamente emitida (llamando a
391 <methodname>Zend_Controller_Response_Abstract::sendResponse()</methodname>
392 ); activando <methodname>returnResponse()</methodname> ) se
393 anulará este comportamiento. </para>
395 <para>Las razones para regresar la respuesta incluyen un deseo
396 de comprobar las excepciones antes de emitir la respuesta,
397 necesidad de hacer un log de diversos aspectos de la
398 respuesta (tales como cabeceras), etc.</para>
403 <sect2 id="zend.controller.front.methods.params">
404 <title>Parámetros de Front Controller</title>
406 <para>En la introducción, se indicó que el front controller también
407 actúa como un registro de los distintos componentes del controlador.
408 Lo hace mediante una familia de métodos "param". Estos métodos le
409 permiten registrar datos arbitrarios -- objetos y variables -- con
410 el front controller, a ser devueltos en cualquier momento en la
411 cadena de dispatch. Estos valores se transmiten al router, al
412 dispatcher, y a los action controllers. Los métodos incluyen:</para>
417 <methodname>setParam($name, $value)</methodname> permite
418 establecer un único parámetro de <varname>$name</varname>
419 con el valor <varname>$value</varname> . </para>
424 <methodname>setParams(array $params)</methodname> permite
425 configurar varios parámetros a la vez usando un array
431 <methodname>getParam($name)</methodname> permite recuperar
432 un único parámetro a la vez, utilizando como identificador a
433 <varname>$name</varname> . </para>
438 <methodname>getParams()</methodname> permite recuperar toda
439 la lista de parámetros a la vez. </para>
444 <methodname>clearParams()</methodname> permite borrar un
445 único parámetro (pasando un string identificador),
446 parámetros con múltiples nombres (pasando un array de
447 strings identificadores), o el stack de parámetros completo
448 (pasando nada). </para>
452 <para>Hay varios parámetros pre-definidos que puede ser seteados para
453 tener usos específicos en la cadena de dispatch:</para>
458 <emphasis>useDefaultControllerAlways</emphasis> se usa para
459 indicar a <link linkend="zend.controller.dispatcher">el
460 dispatcher</link> que utilice el controlador por defecto
461 en el módulo por defecto de cualquier solicitud que no sea
462 dispatchable (es decir, el módulo, el controlador y/o la
463 acción no existen). Por defecto, está en off. </para>
465 <para> Ver <link linkend="zend.controller.exceptions.internal"
466 >MVC Exceptions You May Encounter</link> para
467 información más detallada sobre el uso de este setting.
473 <emphasis>disableOutputBuffering</emphasis> se usa para
474 indicarle a <link linkend="zend.controller.dispatcher">el
475 dispatcher</link> que no debe utilizar output buffering
476 para capturar la salida generada por los controladores de
477 acción. Por defecto, el dispatcher captura cualquier salida
478 y la añade al contenido del cuerpo del objeto respuesta.
484 <emphasis>noViewRenderer</emphasis> se usa para deshabilitar
486 linkend="zend.controller.actionhelpers.viewrenderer"
487 >ViewRenderer</link> . Poniendo este parámetro a true,
488 lo deshabilita. </para>
493 <emphasis>noErrorHandler</emphasis> se usa para deshabilitar
495 linkend="zend.controller.plugins.standard.errorhandler"
496 >Error Handler plugin</link> . Poniendo este parámetro a
497 true, lo deshabilita. </para>
502 <sect2 id="zend.controller.front.subclassing">
503 <title>Extendiendo el Front Controller</title>
505 <para> Para extender el Front Controller, como mínimo que necesitará
506 anular el método <methodname>getInstance()</methodname> : </para>
508 <programlisting language="php"><![CDATA[
509 class My_Controller_Front extends Zend_Controller_Front
511 public static function getInstance()
513 if (null === self::$_instance) {
514 self::$_instance = new self();
517 return self::$_instance;
522 <para> Anulando el método <methodname>getInstance()</methodname> asegura
523 que las subsiguientes llamadas a
524 <methodname>Zend_Controller_Front::getInstance()</methodname>
525 devolverá una instancia de su nueva subclase en lugar de una
526 instancia <classname>Zend_Controller_Front</classname> -- esto es
527 particularmente útil para algunos de los routers alternativos y view
530 <para>Típicamente, no necesitará una subclase del front controller a
531 menos que necesite añadir nuevas funcionalidades (por ejemplo, un
532 plugin autoloader, o una forma de especificar los paths de los
533 action helpers). Algunos de los puntos donde puede querer modificar
534 el comportamiento puede incluir modificar cómo son almacenados los
535 directorios de controladores , o qué router predeterminado o
536 dispatcher se utiliza.</para>