Zend_Controller-FrontController.xml 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- EN-Revision: 15103 -->
  3. <!-- Reviewed: no -->
  4. <sect1 id="zend.controller.front">
  5. <title>El Front Controller</title>
  6. <sect2 id="zend.controller.front.overview">
  7. <title>Introducción</title>
  8. <para>
  9. <classname>Zend_Controller_Front</classname> implementa un <ulink
  10. url="http://www.martinfowler.com/eaaCatalog/frontController.html">Front
  11. Controller pattern</ulink> usado en aplicaciones <ulink
  12. url="http://en.wikipedia.org/wiki/Model-view-controller">Model-View-Controller
  13. (MVC)</ulink>.
  14. Su propósito es inicializar el entorno de la solicitud,
  15. rutear la solicitud entrante, y luego hacer un envío de
  16. cualquier de las acciones descubiertas; le agrega las respuestas
  17. y las regresa cuando se completa el proceso.
  18. </para>
  19. <para>
  20. <classname>Zend_Controller_Front</classname> también implementa el <ulink
  21. url="http://en.wikipedia.org/wiki/Singleton_pattern">Singleton
  22. pattern</ulink>, significando que solo una única instancia de él
  23. puede estar disponible en cualquier momento dado.
  24. Esto le permite actuar también como un registro en el que los demás
  25. objetos pueden extraer del proceso dispatch.
  26. </para>
  27. <para>
  28. <classname>Zend_Controller_Front</classname> registra un <link
  29. linkend="zend.controller.plugins">plugin broker</link> consigo
  30. mismo, permitiendo que diversos eventos que dispara sean observados
  31. por plugins. En muchos casos, esto da el desarrollador la
  32. oportunidad de adaptar el proceso de dispatch al sitio sin la
  33. necesidad de ampliar el Front Controller para añadir funcionalidad.
  34. </para>
  35. <para>
  36. Como mínimo, el front controller necesita una o más paths a
  37. directorios que contengan <link linkend="zend.controller.action">
  38. action controllers</link> a fin de hacer su trabajo.
  39. Una variedad de métodos también pueden ser invocados para seguir
  40. adaptando el medio ambiente del front controller y ese a sus
  41. helper classes.
  42. </para>
  43. <note>
  44. <title>Comportamiento por Defecto</title>
  45. <para>
  46. Por defecto, el front controller carga el <link
  47. linkend="zend.controller.plugins.standard.errorhandler">ErrorHandler</link>
  48. plugin, así como al <link
  49. linkend="zend.controller.actionhelpers.viewrenderer">ViewRenderer</link>
  50. action helper plugin. Estos son para simplificar el manejo de
  51. errores y el view renderering en sus controladores, respectivamente.
  52. </para>
  53. <para>
  54. Para deshabilitar el <code>ErrorHandler</code>, ejecutar lo
  55. siguiente en cualquier momento antes de llamar a
  56. <code>dispatch()</code>:
  57. </para>
  58. <programlisting role="php"><![CDATA[
  59. // Deshabilitar el ErrorHandler plugin:
  60. $front->setParam('noErrorHandler', true);
  61. ]]></programlisting>
  62. <para>
  63. Para deshabilitar el <code>ViewRenderer</code>, haga lo
  64. siguiente antes de llamar a <code>dispatch()</code>:
  65. </para>
  66. <programlisting role="php"><![CDATA[
  67. // Deshabilitar el ViewRenderer helper:
  68. $front->setParam('noViewRenderer', true);
  69. ]]></programlisting>
  70. </note>
  71. </sect2>
  72. <sect2 id="zend.controller.front.methods.primary">
  73. <title>Métodos Básicos</title>
  74. <para>
  75. El front controller tiene varios accessors para establecer su
  76. medio ambiente. Sin embargo, hay tres métodos básicos clave para la
  77. funcionalidad del front controller:
  78. </para>
  79. <sect3 id="zend.controller.front.methods.primary.getinstance">
  80. <title>getInstance()</title>
  81. <para>
  82. <code>getInstance()</code> se utiliza para recuperar una
  83. instancia del front controller. Como el front controller
  84. implementa un patrón Singleton, este también es el único
  85. medio posible para instanciar un objeto front controller.
  86. </para>
  87. <programlisting role="php"><![CDATA[
  88. $front = Zend_Controller_Front::getInstance();
  89. ]]></programlisting>
  90. </sect3>
  91. <sect3 id="zend.controller.front.methods.primary.setcontrollerdirectory">
  92. <title>setControllerDirectory() y addControllerDirectory</title>
  93. <para>
  94. <code>setControllerDirectory()</code> se usa para decirle a <link
  95. linkend="zend.controller.dispatcher">el dispatcher</link>
  96. dónde buscar para los archivos de clase <link
  97. linkend="zend.controller.action">action controller</link>.
  98. Acepta bien un único path o un array asociativo de pares
  99. módulo/path.
  100. </para>
  101. <para>
  102. Como algunos ejemplos:
  103. </para>
  104. <programlisting role="php"><![CDATA[
  105. // Establer el directorio de controladores por defecto:
  106. $front->setControllerDirectory('../application/controllers');
  107. // Establecer varios directorios módulos a la vez:
  108. $front->setControllerDirectory(array(
  109. 'default' => '../application/controllers',
  110. 'blog' => '../modules/blog/controllers',
  111. 'news' => '../modules/news/controllers',
  112. ));
  113. // Agregar un directorio de módulos 'foo':
  114. $front->addControllerDirectory('../modules/foo/controllers', 'foo');
  115. ]]></programlisting>
  116. <note>
  117. <para>
  118. Si usa <code>addControllerDirectory()</code> sin un nombre
  119. de módulo, este establecerá el directorio
  120. <code>default</code> para el módulo -- sobreescribiéndolo
  121. si ya existe.
  122. </para>
  123. </note>
  124. <para>
  125. Puede conseguir la configuración actual para el directorio del
  126. controlador utilizando <code>getControllerDirectory()</code>;
  127. este devolverá un array de pares módulo/directorio.
  128. </para>
  129. </sect3>
  130. <sect3 id="zend.controller.front.methods.primary.addmoduledirectory">
  131. <title>addModuleDirectory() y getModuleDirectory()</title>
  132. <para>
  133. Uno de los aspectos del front controller es que puede <link
  134. linkend="zend.controller.modular"> definir una
  135. estructura modular de directorio</link> para crear
  136. componentes standalone; estos son llamados "módulos".
  137. </para>
  138. <para>
  139. Cada módulo debe estar en su propio directorio y ser un espejo
  140. de la estructura del directorio del módulo por defecto -- es
  141. decir, que debería tener como mínimo un subdirectorio de
  142. "controladores", y típicamente un subdirectorio de "views"
  143. y otros subdirectorios de aplicaciones.
  144. </para>
  145. <para>
  146. <code>addModuleDirectory()</code> permite pasar el nombre de
  147. un directorio que contiene uno o más directorios de módulos.
  148. A continuación lo analiza y los añade como directorios de
  149. controladores al front controller.
  150. </para>
  151. <para>
  152. Después, si quiere determinar el path a un determinado módulo
  153. o al módulo actual, puede llamar a <code>getModuleDirectory()</code>,
  154. opcionalmente puede pasar un nombre de módulo para conseguir el
  155. directorio de ese módulo específico.
  156. </para>
  157. </sect3>
  158. <sect3 id="zend.controller.front.methods.primary.dispatch">
  159. <title>dispatch()</title>
  160. <para>
  161. <code>dispatch(Zend_Controller_Request_Abstract $request = null,
  162. Zend_Controller_Response_Abstract $response = null)</code>
  163. hace el trabajo pesado del front controller. Puede opcionalmente
  164. tomar un <link linkend="zend.controller.request">request
  165. object</link> y/o un <link
  166. linkend="zend.controller.response">response object</link>,
  167. permitiendo al desarrollador pasar objetos peronalizados para
  168. cada uno.
  169. </para>
  170. <para>
  171. Si no se pasa ningun objeto solicitud o respuesta,
  172. <code>dispatch()</code> comprobará por objetos previamente
  173. registrados y utilizará esos o instanciará versiones por defecto
  174. a utilizar en su proceso (en ambos casos, el sabor de HTTP será
  175. utilizado por defecto).
  176. </para>
  177. <para>
  178. Similarmente, <code>dispatch()</code>
  179. comprueba los objetos registrados <link
  180. linkend="zend.controller.router">router</link> y <link
  181. linkend="zend.controller.dispatcher">dispatcher</link>
  182. , instanciando las versiones por defecto de cada uno si ninguno
  183. de ellos se encuentra.
  184. </para>
  185. <para>
  186. El proceso de dispatch tiene tres eventos distintos:
  187. </para>
  188. <itemizedlist>
  189. <listitem><para>Routing</para></listitem>
  190. <listitem><para>Dispatching</para></listitem>
  191. <listitem><para>Response</para></listitem>
  192. </itemizedlist>
  193. <para>
  194. El routing se lleva a cabo exactamente una vez, utilizando los
  195. valores del objeto solicitud cuando se llama a <code>dispatch()</code>.
  196. El dispatching se lleva a cabo en un bucle; una solicitud puede
  197. indicar, bien múltiples acciones de dispatch, o el controlador o
  198. un plugin pueden restablecer el objeto solicitud para forzar
  199. medidas adicionales para dispatch. Cuando todo está hecho,
  200. el front controller devuelve una respuesta.
  201. </para>
  202. </sect3>
  203. <sect3 id="zend.controller.front.methods.primary.run">
  204. <title>run()</title>
  205. <para>
  206. <classname>Zend_Controller_Front::run($path)</classname>
  207. es un método estático que toma simplemente un path a un
  208. directorio que contiene controladores. Obtiene una instancia
  209. del front controller (via
  210. <link
  211. linkend="zend.controller.front.methods.primary.getinstance">getInstance()</link>,
  212. registra el path provisto via <link
  213. linkend="zend.controller.front.methods.primary.setcontrollerdirectory">setControllerDirectory()</link>,
  214. y finalmente <link
  215. linkend="zend.controller.front.methods.primary.dispatch">dispatches</link>.
  216. </para>
  217. <para>
  218. Básicamente, <code>run()</code> es un método conveniente que
  219. pueden utilizarse para setups de sitios que no requieran la
  220. personalización del medio ambiente del front controller.
  221. </para>
  222. <programlisting role="php"><![CDATA[
  223. // Instanciar el front controller, establecer el directorio de controladores,
  224. // y hacer el dispatch fácilmente en en un solo paso:
  225. Zend_Controller_Front::run('../application/controllers');
  226. ]]></programlisting>
  227. </sect3>
  228. </sect2>
  229. <sect2 id="zend.controller.front.methods.environment">
  230. <title>Métodos Accessor Ambientales</title>
  231. <para>
  232. Además de los métodos enumerados anteriormente, hay una serie de
  233. métodos accessor que pueden utilizarse para afectar el entorno
  234. del front controller -- y por lo tanto el ambiente de las clases
  235. a las cuales delega el front controller.
  236. </para>
  237. <itemizedlist>
  238. <listitem>
  239. <para>
  240. <code>resetInstance()</code> puede ser utilizada para
  241. borrar todos los settings actuales. Su objetivo principal
  242. es para testing, pero también puede ser utilizada para
  243. instancias donde desee encadenar múltiples front controllers.
  244. </para>
  245. </listitem>
  246. <listitem>
  247. <para>
  248. <code>(set|get)DefaultControllerName()</code> permite
  249. especificar un nombre diferente para usar en el controlador
  250. por defecto (en caso coontrario, se usa 'index') y
  251. recuperar el valor actual.
  252. Delegan a <link
  253. linkend="zend.controller.dispatcher">el dispatcher</link>.
  254. </para>
  255. </listitem>
  256. <listitem>
  257. <para>
  258. <code>(set|get)DefaultAction()</code> le deja especificar un
  259. nombre diferente a utilizar para la acción predeterminada
  260. (en caso coontrario, se usa 'index') y recuperar el valor
  261. actual.
  262. Delegan a <link
  263. linkend="zend.controller.dispatcher">el dispatcher</link>.
  264. </para>
  265. </listitem>
  266. <listitem>
  267. <para>
  268. <code>(set|get)Request()</code> le permite especificar la
  269. clase u objeto <link
  270. linkend="zend.controller.request">el request</link>
  271. a usar durante el proceso de dispatch y recuperar el objeto
  272. actual. Al setear el objeto solicitud, puede pasarlo en un
  273. nombre de clase de solicitud, en cuyo caso el método va a
  274. cargar el archivo clase y lo instanciará.
  275. </para>
  276. </listitem>
  277. <listitem>
  278. <para>
  279. <code>(set|get)Router()</code> le permite especificar la
  280. clase u objeto <link
  281. linkend="zend.controller.router">el router</link>
  282. a usar durante el proceso de dispatch y recuperar el objeto
  283. actual. Al setear el objeto router, puede pasarlo en un
  284. nombre de clase de router, en cuyo caso el método va a
  285. cargar el archivo clase y lo instanciará.
  286. </para>
  287. <para>
  288. Al recuperar el objeto router, en primer lugar comprueba
  289. para ver si hay alguno presente, y si no, instancia al
  290. router por defecto(reescribe el router).
  291. </para>
  292. </listitem>
  293. <listitem>
  294. <para>
  295. <code>(set|get)BaseUrl()</code> le permite especificar <link
  296. linkend="zend.controller.request.http.baseurl">la URL
  297. base</link> de la cual tirar cuando se rutean peticiones
  298. y recuperar el valor actual. El valor se provee al
  299. objeto solicitud justo antes de rutear.
  300. </para>
  301. </listitem>
  302. <listitem>
  303. <para>
  304. <code>(set|get)Dispatcher()</code> le permite especificar la
  305. clase u objeto <link
  306. linkend="zend.controller.dispatcher">el
  307. dispatcher</link>
  308. a usar durante el proceso de dispatch y recuperar el objeto
  309. actual. Al setear el objeto dispatch, puede pasarlo en un
  310. nombre de clase de dispatcher, en cuyo caso el método va a
  311. cargar el archivo clase y lo instanciará.
  312. </para>
  313. <para>
  314. Al recuperar el objeto dispatch, en primer lugar comprueba
  315. para ver si hay alguno presente, y si no, instancia al
  316. dispatcher por defecto.
  317. </para>
  318. </listitem>
  319. <listitem>
  320. <para>
  321. <code>(set|get)Response()</code> le permite especificar la
  322. clase u objeto <link
  323. linkend="zend.controller.response">response</link>
  324. a usar durante el proceso de dispatch y recuperar el objeto
  325. actual. Al setear el objeto response, puede pasarlo en un
  326. nombre de clase de response, en cuyo caso el método va a
  327. cargar el archivo clase y lo instanciará.
  328. </para>
  329. </listitem>
  330. <listitem>
  331. <para>
  332. <code>registerPlugin(Zend_Controller_Plugin_Abstract $plugin, $stackIndex = null)</code>
  333. le permite registrar <link
  334. linkend="zend.controller.plugins">plugin objects</link>.
  335. Opcionalmente, setting <code>$stackIndex</code>, puede
  336. controlar el orden en que se ejecutarán los plugins.
  337. </para>
  338. </listitem>
  339. <listitem>
  340. <para>
  341. <code>unregisterPlugin($plugin)</code> le permite
  342. desregistrar <link
  343. linkend="zend.controller.plugins">plugin objects</link>.
  344. <code>$plugin</code> puede ser tanto un objeto plugin o un
  345. string que denota la clase de plugin a desregistrar.
  346. </para>
  347. </listitem>
  348. <listitem>
  349. <para>
  350. <code>throwExceptions($flag)</code> se utiliza para
  351. activar/desactivar la capacidad de arrojar excepciones
  352. durante el proceso de dispatch. Por defecto, las excepciones
  353. son capturadas y colocadas en el <link
  354. linkend="zend.controller.response">objeto response
  355. </link>; activando <code>throwExceptions()</code>
  356. se anulará este comportamiento.
  357. </para>
  358. <para>
  359. Para más información, lea <xref
  360. linkend="zend.controller.exceptions" />.
  361. </para>
  362. </listitem>
  363. <listitem>
  364. <para>
  365. <code>returnResponse($flag)</code> se usa para decirle al
  366. front controller cuando regresar la respuesta
  367. (<code>true</code>) desde <code>dispatch()</code>, o si la
  368. respuesta debe ser emitida automáticamente (<code>false</code>).
  369. Por defecto, la respuesta es automáticamente emitida
  370. (llamando a
  371. <classname>Zend_Controller_Response_Abstract::sendResponse()</classname>);
  372. activando <code>returnResponse()</code>) se anulará este
  373. comportamiento.
  374. </para>
  375. <para>
  376. Las razones para regresar la respuesta incluyen un deseo de
  377. comprobar las excepciones antes de emitir la respuesta,
  378. necesidad de hacer un log de diversos aspectos de la respuesta
  379. (tales como cabeceras), etc.
  380. </para>
  381. </listitem>
  382. </itemizedlist>
  383. </sect2>
  384. <sect2 id="zend.controller.front.methods.params">
  385. <title>Parámetros de Front Controller</title>
  386. <para>
  387. En la introducción, se indicó que el front controller también actúa
  388. como un registro de los distintos componentes del controlador.
  389. Lo hace mediante una familia de métodos "param". Estos métodos le
  390. permiten registrar datos arbitrarios -- objetos y variables --
  391. con el front controller, a ser devueltos en cualquier momento
  392. en la cadena de dispatch. Estos valores se transmiten al router,
  393. al dispatcher, y a los action controllers. Los métodos incluyen:
  394. </para>
  395. <itemizedlist>
  396. <listitem>
  397. <para>
  398. <code>setParam($name, $value)</code> permite establecer un
  399. único parámetro de <code>$name</code> con el valor
  400. <code>$value</code>.
  401. </para>
  402. </listitem>
  403. <listitem>
  404. <para>
  405. <code>setParams(array $params)</code> permite configurar
  406. varios parámetros a la vez usando un array asociativo.
  407. </para>
  408. </listitem>
  409. <listitem>
  410. <para>
  411. <code>getParam($name)</code> permite recuperar un único
  412. parámetro a la vez, utilizando como identificador a
  413. <code>$name</code>.
  414. </para>
  415. </listitem>
  416. <listitem>
  417. <para>
  418. <code>getParams()</code> permite recuperar toda la lista de
  419. parámetros a la vez.
  420. </para>
  421. </listitem>
  422. <listitem>
  423. <para>
  424. <code>clearParams()</code> permite borrar un único parámetro
  425. (pasando un string identificador), parámetros con múltiples
  426. nombres (pasando un array de strings identificadores),
  427. o el stack de parámetros completo (pasando nada).
  428. </para>
  429. </listitem>
  430. </itemizedlist>
  431. <para>
  432. Hay varios parámetros pre-definidos que puede ser seteados para
  433. tener usos específicos en la cadena de dispatch:
  434. </para>
  435. <itemizedlist>
  436. <listitem>
  437. <para>
  438. <code>useDefaultControllerAlways</code> se usa para indicar a
  439. <link linkend="zend.controller.dispatcher">el
  440. dispatcher</link> que utilice el controlador por defecto
  441. en el módulo por defecto de cualquier solicitud que no
  442. sea dispatchable (es decir, el módulo, el controlador
  443. y/o la acción no existen). Por defecto, está en off.
  444. </para>
  445. <para>
  446. Ver <xref linkend="zend.controller.exceptions.internal" />
  447. para información más detallada sobre el uso de este setting.
  448. </para>
  449. </listitem>
  450. <listitem>
  451. <para>
  452. <code>disableOutputBuffering</code> se usa para indicarle a <link
  453. linkend="zend.controller.dispatcher">el
  454. dispatcher</link> que no debe utilizar output buffering
  455. para capturar la salida generada por los controladores
  456. de acción. Por defecto, el dispatcher captura cualquier
  457. salida y la añade al contenido del cuerpo del objeto
  458. respuesta.
  459. </para>
  460. </listitem>
  461. <listitem>
  462. <para>
  463. <code>noViewRenderer</code> se usa para deshabilitar el <link
  464. linkend="zend.controller.actionhelpers.viewrenderer">ViewRenderer</link>.
  465. Poniendo este parámetro a true, lo deshabilita.
  466. </para>
  467. </listitem>
  468. <listitem>
  469. <para>
  470. <code>noErrorHandler</code> se usa para deshabilitar el <link
  471. linkend="zend.controller.plugins.standard.errorhandler">Error
  472. Handler plugin</link>. Poniendo este parámetro a true,
  473. lo deshabilita.
  474. </para>
  475. </listitem>
  476. </itemizedlist>
  477. </sect2>
  478. <sect2 id="zend.controller.front.subclassing">
  479. <title>Extendiendo el Front Controller</title>
  480. <para>
  481. Para extender el Front Controller, como mínimo que necesitará
  482. anular el método <code>getInstance()</code>:
  483. </para>
  484. <programlisting role="php"><![CDATA[
  485. class My_Controller_Front extends Zend_Controller_Front
  486. {
  487. public static function getInstance()
  488. {
  489. if (null === self::$_instance) {
  490. self::$_instance = new self();
  491. }
  492. return self::$_instance;
  493. }
  494. }
  495. ]]></programlisting>
  496. <para>
  497. Anulando el método <code>getInstance()</code> asegura que las
  498. subsiguientes llamadas a
  499. <classname>Zend_Controller_Front::getInstance()</classname>
  500. devolverá una instancia de su nueva subclase en lugar de una
  501. instancia
  502. <classname>Zend_Controller_Front</classname> -- esto es
  503. particularmente útil para algunos de los routers alternativos y
  504. view helpers.
  505. </para>
  506. <para>
  507. Típicamente, no necesitará una subclase del front controller
  508. a menos que necesite añadir nuevas funcionalidades
  509. (por ejemplo, un plugin autoloader, o una forma de especificar
  510. los paths de los action helpers). Algunos de los puntos donde puede
  511. querer modificar el comportamiento puede incluir modificar cómo
  512. son almacenados los directorios de controladores , o qué router
  513. predeterminado o dispatcher se utiliza.
  514. </para>
  515. </sect2>
  516. </sect1>
  517. <!--
  518. vim:se ts=4 sw=4 et:
  519. -->