Zend_Controller-FrontController.xml 25 KB

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