Zend_Controller-FrontController.xml 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  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">the 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 estructura
  134. modular de directorio</link> para crear componentes
  135. 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 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. Similarly, <code>dispatch()</code> checks for registered <link
  178. linkend="zend.controller.router">router</link> and <link
  179. linkend="zend.controller.dispatcher">dispatcher</link>
  180. objects, instantiating the default versions of each if none is
  181. found.
  182. </para>
  183. <para>
  184. The dispatch process has three distinct events:
  185. </para>
  186. <itemizedlist>
  187. <listitem><para>Routing</para></listitem>
  188. <listitem><para>Dispatching</para></listitem>
  189. <listitem><para>Response</para></listitem>
  190. </itemizedlist>
  191. <para>
  192. Routing takes place exactly once, using the values in the
  193. request object when <code>dispatch()</code> is called.
  194. Dispatching takes place in a loop; a request may either indicate
  195. multiple actions to dispatch, or the controller or a plugin may
  196. reset the request object to force additional actions to
  197. dispatch. When all is done, the front controller returns a
  198. response.
  199. </para>
  200. </sect3>
  201. <sect3 id="zend.controller.front.methods.primary.run">
  202. <title>run()</title>
  203. <para>
  204. <classname>Zend_Controller_Front::run($path)</classname> is a static
  205. method taking simply a path to a directory containing
  206. controllers. It fetches a front controller instance (via
  207. <link
  208. linkend="zend.controller.front.methods.primary.getinstance">getInstance()</link>,
  209. registers the path provided via <link
  210. linkend="zend.controller.front.methods.primary.setcontrollerdirectory">setControllerDirectory()</link>,
  211. and finally <link
  212. linkend="zend.controller.front.methods.primary.dispatch">dispatches</link>.
  213. </para>
  214. <para>
  215. Basically, <code>run()</code> is a convenience method that can
  216. be used for site setups that do not require customization of the
  217. front controller environment.
  218. </para>
  219. <programlisting role="php"><![CDATA[
  220. // Instantiate front controller, set controller directory, and dispatch in one
  221. // easy step:
  222. Zend_Controller_Front::run('../application/controllers');
  223. ]]></programlisting>
  224. </sect3>
  225. </sect2>
  226. <sect2 id="zend.controller.front.methods.environment">
  227. <title>Environmental Accessor Methods</title>
  228. <para>
  229. In addition to the methods listed above, there are a number of
  230. accessor methods that can be used to affect the front controller
  231. environment -- and thus the environment of the classes to which the
  232. front controller delegates.
  233. </para>
  234. <itemizedlist>
  235. <listitem>
  236. <para>
  237. <code>resetInstance()</code> can be used to clear all
  238. current settings. Its primary purpose is for testing, but it
  239. can also be used for instances where you wish to chain
  240. together multiple front controllers.
  241. </para>
  242. </listitem>
  243. <listitem>
  244. <para>
  245. <code>(set|get)DefaultControllerName()</code> let you
  246. specify a different name to use for the default controller
  247. ('index' is used otherwise) and retrieve the current value.
  248. They proxy to <link
  249. linkend="zend.controller.dispatcher">the
  250. dispatcher</link>.
  251. </para>
  252. </listitem>
  253. <listitem>
  254. <para>
  255. <code>(set|get)DefaultAction()</code> let you specify a
  256. different name to use for the default action ('index' is
  257. used otherwise) and retrieve the current value. They proxy
  258. to <link linkend="zend.controller.dispatcher">the
  259. dispatcher</link>.
  260. </para>
  261. </listitem>
  262. <listitem>
  263. <para>
  264. <code>(set|get)Request()</code> let you specify <link
  265. linkend="zend.controller.request">the request</link>
  266. class or object to use during the dispatch process and to
  267. retrieve the current object. When setting the request
  268. object, you may pass in a request class name, in which case
  269. the method will load the class file and instantiate it.
  270. </para>
  271. </listitem>
  272. <listitem>
  273. <para>
  274. <code>(set|get)Router()</code> let you specify <link
  275. linkend="zend.controller.router">the router</link>
  276. class or object to use during the dispatch process and to
  277. retrieve the current object. When setting the router
  278. object, you may pass in a router class name, in which case
  279. the method will load the class file and instantiate it.
  280. </para>
  281. <para>
  282. When retrieving the router object, it first checks to see if
  283. one is present, and if not, instantiates the default router
  284. (rewrite router).
  285. </para>
  286. </listitem>
  287. <listitem>
  288. <para>
  289. <code>(set|get)BaseUrl()</code> let you specify <link
  290. linkend="zend.controller.request.http.baseurl">the base
  291. URL</link> to strip when routing requests and to
  292. retrieve the current value. The value is provided to the
  293. request object just prior to routing.
  294. </para>
  295. </listitem>
  296. <listitem>
  297. <para>
  298. <code>(set|get)Dispatcher()</code> let you specify <link
  299. linkend="zend.controller.dispatcher">the
  300. dispatcher</link> class or object to use during the
  301. dispatch process and retrieve the current object. When
  302. setting the dispatcher object, you may pass in a dispatcher
  303. class name, in which case the method will load the class
  304. file and instantiate it.
  305. </para>
  306. <para>
  307. When retrieving the dispatcher object, it first checks to see if
  308. one is present, and if not, instantiates the default
  309. dispatcher.
  310. </para>
  311. </listitem>
  312. <listitem>
  313. <para>
  314. <code>(set|get)Response()</code> let you specify <link
  315. linkend="zend.controller.response">the response</link>
  316. class or object to use during the dispatch process and to
  317. retrieve the current object. When setting the response
  318. object, you may pass in a response class name, in which case
  319. the method will load the class file and instantiate it.
  320. </para>
  321. </listitem>
  322. <listitem>
  323. <para>
  324. <code>registerPlugin(Zend_Controller_Plugin_Abstract $plugin, $stackIndex = null)</code>
  325. allows you to register <link
  326. linkend="zend.controller.plugins">plugin objects</link>.
  327. By setting the optional <code>$stackIndex</code>, you can
  328. control the order in which plugins will execute.
  329. </para>
  330. </listitem>
  331. <listitem>
  332. <para>
  333. <code>unregisterPlugin($plugin)</code> let you
  334. unregister <link
  335. linkend="zend.controller.plugins">plugin objects</link>.
  336. <code>$plugin</code> may be either a plugin object or a
  337. string denoting the class of plugin to unregister.
  338. </para>
  339. </listitem>
  340. <listitem>
  341. <para>
  342. <code>throwExceptions($flag)</code> is used to turn on/off
  343. the ability to throw exceptions during the dispatch process.
  344. By default, exceptions are caught and placed in the <link
  345. linkend="zend.controller.response">response
  346. object</link>; turning on <code>throwExceptions()</code>
  347. will override this behaviour.
  348. </para>
  349. <para>
  350. For more information, read <xref
  351. linkend="zend.controller.exceptions" />.
  352. </para>
  353. </listitem>
  354. <listitem>
  355. <para>
  356. <code>returnResponse($flag)</code> is used to tell the front
  357. controller whether to return the response
  358. (<code>true</code>) from <code>dispatch()</code>, or if the
  359. response should be automatically emitted
  360. (<code>false</code>). By default, the response is
  361. automatically emitted (by calling
  362. <classname>Zend_Controller_Response_Abstract::sendResponse()</classname>);
  363. turning on <code>returnResponse()</code> will override this
  364. behaviour.
  365. </para>
  366. <para>
  367. Reasons to return the response include a desire to check for
  368. exceptions prior to emitting the response, needing to log
  369. various aspects of the response (such as headers), etc.
  370. </para>
  371. </listitem>
  372. </itemizedlist>
  373. </sect2>
  374. <sect2 id="zend.controller.front.methods.params">
  375. <title>Front Controller Parameters</title>
  376. <para>
  377. In the introduction, we indicated that the front controller also
  378. acts as a registry for the various controller components. It does so
  379. through a family of "param" methods. These methods allow you to
  380. register arbitrary data -- objects and variables -- with the front
  381. controller to be retrieved at any time in the dispatch chain. These
  382. values are passed on to the router, dispatcher, and action
  383. controllers. The methods include:
  384. </para>
  385. <itemizedlist>
  386. <listitem>
  387. <para>
  388. <code>setParam($name, $value)</code> allows you to set a
  389. single parameter of <code>$name</code> with value
  390. <code>$value</code>.
  391. </para>
  392. </listitem>
  393. <listitem>
  394. <para>
  395. <code>setParams(array $params)</code> allows you to set
  396. multiple parameters at once using an associative array.
  397. </para>
  398. </listitem>
  399. <listitem>
  400. <para>
  401. <code>getParam($name)</code> allows you to retrieve a single
  402. parameter at a time, using <code>$name</code> as the
  403. identifier.
  404. </para>
  405. </listitem>
  406. <listitem>
  407. <para>
  408. <code>getParams()</code> allows you to retrieve the entire
  409. list of parameters at once.
  410. </para>
  411. </listitem>
  412. <listitem>
  413. <para>
  414. <code>clearParams()</code> allows you to clear a single
  415. parameter (by passing a string identifier), multiple named
  416. parameters (by passing an array of string identifiers), or the
  417. entire parameter stack (by passing nothing).
  418. </para>
  419. </listitem>
  420. </itemizedlist>
  421. <para>
  422. There are several pre-defined parameters that may be set that have
  423. specific uses in the dispatch chain:
  424. </para>
  425. <itemizedlist>
  426. <listitem>
  427. <para>
  428. <code>useDefaultControllerAlways</code> is used to hint to
  429. <link linkend="zend.controller.dispatcher">the
  430. dispatcher</link> to use the default controller in the
  431. default module for any request that is not dispatchable
  432. (i.e., the module, controller, and/or action do not exist).
  433. By default, this is off.
  434. </para>
  435. <para>
  436. See <xref linkend="zend.controller.exceptions.internal" />
  437. for more detailed information on using this setting.
  438. </para>
  439. </listitem>
  440. <listitem>
  441. <para>
  442. <code>disableOutputBuffering</code> is used to hint to <link
  443. linkend="zend.controller.dispatcher">the
  444. dispatcher</link> that it should not use output
  445. buffering to capture output generated by action controllers.
  446. By default, the dispatcher captures any output and appends
  447. it to the response object body content.
  448. </para>
  449. </listitem>
  450. <listitem>
  451. <para>
  452. <code>noViewRenderer</code> is used to disable the <link
  453. linkend="zend.controller.actionhelpers.viewrenderer">ViewRenderer</link>.
  454. Set this parameter to true to disable it.
  455. </para>
  456. </listitem>
  457. <listitem>
  458. <para>
  459. <code>noErrorHandler</code> is used to disable the <link
  460. linkend="zend.controller.plugins.standard.errorhandler">Error
  461. Handler plugin</link>. Set this parameter to true to
  462. disable it.
  463. </para>
  464. </listitem>
  465. </itemizedlist>
  466. </sect2>
  467. <sect2 id="zend.controller.front.subclassing">
  468. <title>Extending the Front Controller</title>
  469. <para>
  470. To extend the Front Controller, at the very minimum you will need
  471. to override the <code>getInstance()</code> method:
  472. </para>
  473. <programlisting role="php"><![CDATA[
  474. class My_Controller_Front extends Zend_Controller_Front
  475. {
  476. public static function getInstance()
  477. {
  478. if (null === self::$_instance) {
  479. self::$_instance = new self();
  480. }
  481. return self::$_instance;
  482. }
  483. }
  484. ]]></programlisting>
  485. <para>
  486. Overriding the <code>getInstance()</code> method ensures that
  487. subsequent calls to
  488. <classname>Zend_Controller_Front::getInstance()</classname> will return an
  489. instance of your new subclass instead of a
  490. <classname>Zend_Controller_Front</classname> instance -- this is particularly
  491. useful for some of the alternate routers and view helpers.
  492. </para>
  493. <para>
  494. Typically, you will not need to subclass the front controller unless
  495. you need to add new functionality (for instance, a plugin
  496. autoloader, or a way to specify action helper paths). Some points
  497. where you may want to alter behaviour may include modifying how
  498. controller directories are stored, or what default router or
  499. dispatcher are used.
  500. </para>
  501. </sect2>
  502. </sect1>
  503. <!--
  504. vim:se ts=4 sw=4 et:
  505. -->