2
0

Zend_Controller-ActionController.xml 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- EN-Revision: 15103 -->
  3. <!-- Reviewed: no -->
  4. <sect1 id="zend.controller.action">
  5. <title>Controladores de Acción</title>
  6. <sect2 id="zend.controller.action.introduction">
  7. <title>Introducción</title>
  8. <para>
  9. <classname>Zend_Controller_Action</classname> es una clase abstracta
  10. que puede utilizar para implementar controladores de acción
  11. (Action Controllers) para usar con el Front Controller al crear un
  12. un sitio basado en el patrón Modelo-Vista-Controlador (MVC).
  13. </para>
  14. <para>
  15. Para usar <classname>Zend_Controller_Action</classname>, necesitará
  16. hacerla una subclase en sus clases actuales de controladores de
  17. acción (o hacerla una subclase para crear su propia clase base de
  18. acción de controladores).
  19. La operación más elemental es hacerla una subclase, y crear métodos
  20. de acción que corresponden a las diversas acciones que desee que el
  21. contralor maneje para su sitio.
  22. El manejo del ruteo y envío de
  23. <classname>Zend_Controller</classname> descubrirá por sí mismo
  24. cualquier método que termine en 'Action' en su clase, como posibles
  25. acciones del controlador.
  26. </para>
  27. <para>
  28. Por ejemplo, digamos que su clase se define como sigue:
  29. </para>
  30. <programlisting role="php"><![CDATA[
  31. class FooController extends Zend_Controller_Action
  32. {
  33. public function barAction()
  34. {
  35. // hacer algo
  36. }
  37. public function bazAction()
  38. {
  39. // hacer algo
  40. }
  41. }
  42. ]]></programlisting>
  43. <para>
  44. La clase de arriba <code>FooController</code> (el controlador
  45. <code>foo</code>) define dos acciones, <code>bar</code> y
  46. <code>baz</code>.
  47. </para>
  48. <para>
  49. Se pueden lograr muchas cosas más, tales como personalizar
  50. la inicialización de acciones, las acciones a llamar por defecto no
  51. deberían especificar ninguna acción (o una acción inválida),
  52. ganchos de pre y post despacho, y una variedad de métodos ayudantes.
  53. Este capítulo sirve como panorama de la funcionalidad del
  54. controlador de acciones.
  55. </para>
  56. <note>
  57. <title>Comportamiento por Defecto</title>
  58. <para>
  59. Por defecto, el <link linkend="zend.controller.front">front
  60. controller</link> habilita al ayudante de acción <link
  61. linkend="zend.controller.actionhelpers.viewrenderer">ViewRenderer</link>.
  62. Este ayudante toma a su cargo la inyección del objeto "view"
  63. en el contralor, así como compatibilizar automáticamente las
  64. vistas. Usted podrá desactivarlo dentro de su contralor de
  65. acción por uno de los métodos siguientes:
  66. </para>
  67. <programlisting role="php"><![CDATA[
  68. class FooController extends Zend_Controller_Action
  69. {
  70. public function init()
  71. {
  72. // Local a este controlador únicamente; afecta a todas las acciones
  73. // al cargarse en init:
  74. $this->_helper->viewRenderer->setNoRender(true);
  75. // Globalmente:
  76. $this->_helper->removeHelper('viewRenderer');
  77. // También globalmente, pero tendría que ser en conjunción con la
  78. // versión local con el fin de propagarlo para este controlador:
  79. Zend_Controller_Front::getInstance()
  80. ->setParam('noViewRenderer', true);
  81. }
  82. }
  83. ]]></programlisting>
  84. <para>
  85. <code>initView()</code>, <code>getViewScript()</code>,
  86. <code>render()</code>, y <code>renderScript()</code> cada
  87. proxy al <code>ViewRenderer</code> a menos que el ayudante no
  88. esté como ayudante intermediario o no se haya establecido el
  89. flag de <code>noViewRenderer</code>.
  90. </para>
  91. <para>
  92. También puede simplemente desactivarse para una prestación
  93. individual ajustando el flag <code>noRender</code> de
  94. <code>ViewRenderer</code>:
  95. </para>
  96. <programlisting role="php"><![CDATA[
  97. class FooController extends Zend_Controller_Action
  98. {
  99. public function barAction()
  100. {
  101. // deshabilitar el autorendering para esta acción solamente:
  102. $this->_helper->viewRenderer->setNoRender();
  103. }
  104. }
  105. ]]></programlisting>
  106. <para>
  107. Las principales razones para desactivar
  108. <code>ViewRenderer</code> son si usted simplemente no necesita
  109. una objeto "view" o si no está mostrándolos via view scripts
  110. (por ejemplo, cuando se utiliza un controlador de acción
  111. para alimentar a los protocolos de un servicio web como SOAP,
  112. XML-RPC, o REST). En muchos casos, nunca necesitará desactivar
  113. a <code>ViewRenderer</code> globalmente, sólo selectivamente
  114. dentro de los distintos controladores o acciones.
  115. </para>
  116. </note>
  117. </sect2>
  118. <sect2 id="zend.controller.action.initialization">
  119. <title>Inicialización de Objectos</title>
  120. <para>
  121. Si bien siempre puede anular el contolador de acción del
  122. constructor, no lo recomendamos.
  123. <classname>Zend_Controller_Action::__construct()</classname>
  124. realiza algunas tareas importantes, tales como registrar los
  125. objetos de solicitud y respuesta, así como los argumentos de
  126. cualquier invocación personalizada pasados desde el front
  127. controller. Si debe anular el constructor, asegúrese de llamar a
  128. <code>parent::__construct($request, $response, $invokeArgs)</code>.
  129. </para>
  130. <para>
  131. La manera más apropiada de personalizar la instanciación es
  132. utilizar el método <code>init()</code>, el cual es llamado como la
  133. última tarea de <code>__construct()</code>.
  134. Por ejemplo, si se quiere conectar a una base de datos en la
  135. instanciación:
  136. </para>
  137. <programlisting role="php"><![CDATA[
  138. class FooController extends Zend_Controller_Action
  139. {
  140. public function init()
  141. {
  142. $this->db = Zend_Db::factory('Pdo_Mysql', array(
  143. 'host' => 'myhost',
  144. 'username' => 'user',
  145. 'password' => 'XXXXXXX',
  146. 'dbname' => 'website'
  147. ));
  148. }
  149. }
  150. ]]></programlisting>
  151. </sect2>
  152. <sect2 id="zend.controller.action.prepostdispatch">
  153. <title>Ganchos de Pre- and Post-Despacho</title>
  154. <para>
  155. <classname>Zend_Controller_Action</classname> especifica dos
  156. métodos que pueden ser llamados para marcar una solicitud de acción,
  157. <code>preDispatch()</code> y <code>postDispatch()</code>.
  158. Estas pueden ser útiles de varias maneras: verificar la
  159. autenticación y ACLs antes de ejecutar una acción (llamando a
  160. <code>_forward()</code> en <code>preDispatch()</code>, se saltará
  161. la acción), por ejemplo, o colocando contenido generado en una
  162. plantilla general del sitio (<code>postDispatch()</code>).
  163. </para>
  164. </sect2>
  165. <sect2 id="zend.controller.action.accessors">
  166. <title>Accessors (Accededores)</title>
  167. <para>
  168. Con el objeto, se registran una serie de objetos y variables,
  169. y cada uno tiene métodos de acceso.
  170. </para>
  171. <itemizedlist>
  172. <listitem><para>
  173. <emphasis>Objecto Requerimiento</emphasis>: <code>getRequest()</code>
  174. puede ser utilizado para recuperar el objeto solicitud
  175. utilizado para llamar a la acción.
  176. </para></listitem>
  177. <listitem>
  178. <para>
  179. <emphasis>Objecto Respuesta</emphasis>:
  180. <code>getResponse()</code> puede ser utilizado para
  181. recuperar el objeto respuesta agregando la respuesta final.
  182. Algunas llamadas típicas podrían ser:
  183. </para>
  184. <programlisting role="php"><![CDATA[
  185. $this->getResponse()->setHeader('Content-Type', 'text/xml');
  186. $this->getResponse()->appendBody($content);
  187. ]]></programlisting>
  188. </listitem>
  189. <listitem>
  190. <para>
  191. <emphasis>Argumentos de Invocación</emphasis>: el front
  192. controller puede empujar parámetros al router, al
  193. despachador, y al controlador de acción. Para recuperarlos,
  194. use <code>getInvokeArg($key)</code>; por otra parte, se
  195. puede traer toda la lista utilizando
  196. <code>getInvokeArgs()</code>.
  197. </para>
  198. </listitem>
  199. <listitem>
  200. <para>
  201. <emphasis>Parámetros de Requerimientos</emphasis>:
  202. La objeto solicitud agrega parámetros de solicitud,
  203. como cualquiera de los parámetros _GET o _POST,
  204. o parámetros del usuario especificados en la información
  205. del path de la URL. Para recuperarlos, use
  206. <code>_getParam($key)</code> o <code>_getAllParams()</code>.
  207. También se pueden establecer parámetros de solicitud usando
  208. <code>_setParam()</code>; lo que es útil cuando se reenvían
  209. a acciones adicionales.
  210. </para>
  211. <para>
  212. Para probar si un parámetro existe o no (muy útil para
  213. bifurcaciones lógicas), use <code>_hasParam($key)</code>.
  214. </para>
  215. <note>
  216. <para>
  217. <code>_getParam()</code> puede tomar opcionalmente un
  218. segundo argumento que contiene un valor por defecto a
  219. utilizar si el parámetro no está establecido o está
  220. vacío. Usándolo elimina la necesidad de llamar
  221. previamente a <code>_hasParam()</code> para
  222. recuperar un valor:
  223. </para>
  224. <programlisting role="php"><![CDATA[
  225. // Usar por defecto el valor 1 si el id no está establecido
  226. $id = $this->_getParam('id', 1);
  227. // En lugar de:
  228. if ($this->_hasParam('id') {
  229. $id = $this->_getParam('id');
  230. } else {
  231. $id = 1;
  232. }
  233. ]]></programlisting>
  234. </note>
  235. </listitem>
  236. </itemizedlist>
  237. </sect2>
  238. <sect2 id="zend.controller.action.viewintegration">
  239. <title>Integración de Vistas</title>
  240. <note id="zend.controller.action.viewintegration.viewrenderer">
  241. <title>Integración de la Vista por Defecto via ViewRenderer</title>
  242. <para>
  243. El contenido de esta sección sólo es válida cuando usted tiene
  244. explícitamente deshabilitado a
  245. <link linkend="zend.controller.actionhelpers.viewrenderer">ViewRenderer</link>.
  246. De lo contrario, puede saltarse esta sección.
  247. </para>
  248. </note>
  249. <para>
  250. <classname>Zend_Controller_Action</classname> proporciona un
  251. mecanismo rudimentario y flexible para ver la integración.
  252. Hay dos métodos para lograrlo, <code>initView()</code> y
  253. <code>render()</code>; el anterior método <code>$view</code>
  254. carga la propiedad pública, y este último muestra una vista en
  255. base a la acción requerida actual, utilizando la jerarquía del
  256. directorio para determinar el path del script.
  257. </para>
  258. <sect3 id="zend.controller.action.viewintegration.initview">
  259. <title>Inicialización de la Vista</title>
  260. <para>
  261. <code>initView()</code> inicializa el objeto vista.
  262. <code>render()</code> llama a <code>initView()</code>
  263. con el fin de recuperar el objeto vista, pero puede ser
  264. iniciada en cualquier momento; por defecto introduce
  265. información a la propiedad de <code>$view</code> con un objeto
  266. <classname>Zend_View</classname>, pero se puede usar cualquier
  267. clase que implemente <classname>Zend_View_Interface</classname>.
  268. Si <code>$view</code> ya ha sido inicializada, simplemente
  269. devuelve esa propiedad.
  270. </para>
  271. <para>
  272. La implementación por defecto hace la siguiente hipótesis de la
  273. estructura del directorio:
  274. </para>
  275. <programlisting role="php"><![CDATA[
  276. applicationOrModule/
  277. controllers/
  278. IndexController.php
  279. views/
  280. scripts/
  281. index/
  282. index.phtml
  283. helpers/
  284. filters/
  285. ]]></programlisting>
  286. <para>
  287. En otras palabras, los scripts de vista se supone están en el
  288. subdirectorio <code>views/scripts/</code>, y en el subdirectorio
  289. <code>views</code> se supone que contiene funcionalidades
  290. hermanas (ayudantes, filtros). Al determinar el nombre y el
  291. path del script, el directorio <code>views/scripts/</code>
  292. será utilizado como el path base, con directorios nombrados
  293. después que los controladores individuales proporcionen una
  294. jerarquía a los scripts de vista.
  295. </para>
  296. </sect3>
  297. <sect3 id="zend.controller.action.viewintegration.render">
  298. <title>Suministrando las Vistas</title>
  299. <para>
  300. <code>render()</code> tiene la siguiente firma:
  301. </para>
  302. <programlisting role="php"><![CDATA[
  303. string render(string $action = null,
  304. string $name = null,
  305. bool $noController = false);
  306. ]]></programlisting>
  307. <para>
  308. <code>render()</code> suministra un script de vista.
  309. Si no se pasan argumentos, se supone que el script requerido es
  310. <code>[controller]/[action].phtml</code> (donde
  311. <code>.phtml</code> es el valor de la propiedad
  312. <code>$viewSuffix</code>).
  313. Pasándole un valor a <code>$action</code> suministrará esa
  314. plantilla en al subdirectorio <code>[controller]</code>. Para
  315. anular el subdirectorio <code>[controller]</code> ponga un
  316. valor verdadero en <code>$noController</code>.
  317. Por último, las plantillas son suministradas en el objeto
  318. respuesta; si desea suministrar a un determinado
  319. <link linkend="zend.controller.response.namedsegments">
  320. named segment</link> en el objeto respuesta, pase un valor a
  321. <code>$name</code>.
  322. </para>
  323. <note><para>
  324. Dado que el controlador y los nombres de acción pueden
  325. contener caracteres delimitadores como '_', '.', y '-',
  326. <code>render()</code> los normaliza a '-' para determinar
  327. el nombre del script. Internamente, utiliza los
  328. delimitadores de palabra y de path del despachador para
  329. hacer esta normalización. Así, una solicitud a
  330. <code>/foo.bar/baz-bat</code> suministrará el script
  331. <code>foo-bar/baz-bat.phtml</code>.
  332. Si su método de acción contiene camelCasing, recuerde que
  333. esto se traducirá en palabras separadas por '-'
  334. al determinar el nombre del archivo del script de vista.
  335. </para></note>
  336. <para>
  337. Algunos ejemplos:
  338. </para>
  339. <programlisting role="php"><![CDATA[
  340. class MyController extends Zend_Controller_Action
  341. {
  342. public function fooAction()
  343. {
  344. // Suministra my/foo.phtml
  345. $this->render();
  346. // Suministra my/bar.phtml
  347. $this->render('bar');
  348. // Suministra baz.phtml
  349. $this->render('baz', null, true);
  350. // Suministra my/login.phtml al segmento 'form' del
  351. // objeto respuesta
  352. $this->render('login', 'form');
  353. // Suministra site.phtml al segmento 'page' del objeto
  354. // respuesta; no usa el subdirectorio 'my/'
  355. $this->render('site', 'page', true);
  356. }
  357. public function bazBatAction()
  358. {
  359. // Suministra my/baz-bat.phtml
  360. $this->render();
  361. }
  362. }
  363. ]]></programlisting>
  364. </sect3>
  365. </sect2>
  366. <sect2 id="zend.controller.action.utilmethods">
  367. <title>Métodos Utilitarios</title>
  368. <para>
  369. Además de los accesadores y de los métodos de integración de vistas,
  370. <classname>Zend_Controller_Action</classname> tiene varios
  371. métodos utilitarios para realizar tareas comunes dentro de sus
  372. métodos de acción (o de pre-/post-despacho).
  373. </para>
  374. <itemizedlist>
  375. <listitem>
  376. <para>
  377. <code>_forward($action, $controller = null, $module = null,
  378. array $params = null)</code>: realiza otra acción. Si es
  379. llamado en <code>preDispatch()</code>, la acción actualmente
  380. requerida se saltará en favor de la nueva.
  381. De lo contrario, después de procesar la acción actual,
  382. se ejecutará la acción solicitada en _forward().
  383. </para>
  384. </listitem>
  385. <listitem>
  386. <para>
  387. <code>_redirect($url, array $options =
  388. array())</code>: redireccionar a otro lugar.
  389. Este método toma una URL y un conjunto de opciones.
  390. Por defecto, realiza una redirección HTTP 302.
  391. </para>
  392. <para>
  393. Las opciones pueden incluir uno o más de los siguientes:
  394. </para>
  395. <itemizedlist>
  396. <listitem>
  397. <para>
  398. <emphasis>exit:</emphasis> ya sea para salir
  399. inmediatamente o no. Si así lo solicita, limpiamente
  400. cerrará cualquier sesión abierta y realizará
  401. la redirección.
  402. </para>
  403. <para>
  404. Puede configurar esta opción globalmente en el
  405. controlador utilizando el accesador
  406. <code>setRedirectExit()</code>.
  407. </para>
  408. </listitem>
  409. <listitem>
  410. <para>
  411. <emphasis>prependBase:</emphasis> ya sea
  412. anteponiendo o no la base URL registrada con el
  413. objeto solicitud a la URL provista.
  414. </para>
  415. <para>
  416. Puede configurar esta opción globalmente en el
  417. controlador utilizando el accesador
  418. <code>setRedirectPrependBase()</code>.
  419. </para>
  420. </listitem>
  421. <listitem>
  422. <para>
  423. <emphasis>code:</emphasis> qué código HTTP
  424. utilizar en la redirección. Por defecto,
  425. se utiliza un HTTP 302; se puede utilizar cualquier
  426. código entre 301 y 306.
  427. </para>
  428. <para>
  429. Puede configurar esta opción globalmente en el
  430. controlador utilizando el accesador
  431. <code>setRedirectCode()</code>.
  432. </para>
  433. </listitem>
  434. </itemizedlist>
  435. </listitem>
  436. </itemizedlist>
  437. </sect2>
  438. <sect2 id="zend.controller.action.subclassing">
  439. <title>Controladores de Acción y haciendo Subclases</title>
  440. <para>
  441. Por diseño, <classname>Zend_Controller_Action</classname>
  442. debe ser "subclaseada" a fin de crear un controlador de acción.
  443. Como mínimo, necesitará definir los métodos de acción que podrá
  444. llamar el controlador.
  445. </para>
  446. <para>
  447. Además de crear una funcionalidad útil para su aplicaciones web,
  448. también puede encontrar que está repitiendo demasiado los mismos
  449. setups o métodos utilitarios en sus diferentes controladores;
  450. si así fuera, creando una clase base común del controlador
  451. que extienda <classname>Zend_Controller_Action</classname> puede
  452. resolver esta redundacia.
  453. </para>
  454. <example id="zend.controller.action.subclassing.example-call">
  455. <title>Manejando Acciones No Existentes</title>
  456. <para>
  457. Si hay una solicitud a un controlador que incluye un método de
  458. acción no definido, se invocará a
  459. <classname>Zend_Controller_Action::__call()</classname>.
  460. <code>__call()</code> es, por supuesto, el método mágico de PHP
  461. para la sobrecarga del método.
  462. </para>
  463. <para>
  464. Por defecto, este método lanza un
  465. <classname>Zend_Controller_Action_Exception</classname>
  466. indicando que el método no se encuentró en el controlador.
  467. Si el método requerido termina en 'Action', la suposición es
  468. que una acción fue solicitada y no existe; tales errores
  469. resultan en una excepción con un código 404.
  470. Todos los demás métodos resultan en una excepción con un
  471. código 500. Esto le permite diferenciar fácilmente entre una
  472. página no encontrada y errores de aplicación con su
  473. manejador de errores.
  474. </para>
  475. <para>
  476. Usted debe anular esta funcionalidad si desea realizar otras
  477. operaciones. Por ejemplo, si desea mostrar un mensaje de error,
  478. usted podría escribir algo como esto:
  479. </para>
  480. <programlisting role="php"><![CDATA[
  481. class MyController extends Zend_Controller_Action
  482. {
  483. public function __call($method, $args)
  484. {
  485. if ('Action' == substr($method, -6)) {
  486. // Si no se encontró el método de la acción, suministrar la
  487. // plantilla de error
  488. return $this->render('error');
  489. }
  490. // todos los otros métodos lanzan una excepción
  491. throw new Exception('Se ha llamado al método "'
  492. . $method
  493. . '" que es inválido',
  494. 500);
  495. }
  496. }
  497. ]]></programlisting>
  498. <para>
  499. Otra posibilidad es que puede querer avanzar a un controlador
  500. de página por defecto:
  501. </para>
  502. <programlisting role="php"><![CDATA[
  503. class MyController extends Zend_Controller_Action
  504. {
  505. public function indexAction()
  506. {
  507. $this->render();
  508. }
  509. public function __call($method, $args)
  510. {
  511. if ('Action' == substr($method, -6)) {
  512. // Si no se encontró el método de acción, avance a la
  513. // acción index
  514. return $this->_forward('index');
  515. }
  516. // todos los otros métodos lanzan una excepción
  517. throw new Exception('Se ha llamado al método "'
  518. . $method
  519. . '" que es inválido',
  520. 500);
  521. }
  522. }
  523. ]]></programlisting>
  524. </example>
  525. <para>
  526. Además de sobrecargar <code>__call()</code>, cada uno de los
  527. métodos gancho de inicialización, utilidad, accesador, vista,
  528. y despacho mencionados anteriormente en este capítulo pueden ser
  529. anulados a fin de personalizar sus controladores.
  530. Como ejemplo, si está almacenando su objeto vista en un registro,
  531. quizás desee modificar su método <code>initView()</code> con código
  532. parecido al siguiente:
  533. </para>
  534. <programlisting role="php"><![CDATA[
  535. abstract class My_Base_Controller extends Zend_Controller_Action
  536. {
  537. public function initView()
  538. {
  539. if (null === $this->view) {
  540. if (Zend_Registry::isRegistered('view')) {
  541. $this->view = Zend_Registry::get('view');
  542. } else {
  543. $this->view = new Zend_View();
  544. $this->view->setBasePath(dirname(__FILE__) . '/../views');
  545. }
  546. }
  547. return $this->view;
  548. }
  549. }
  550. ]]></programlisting>
  551. <para>
  552. Es de esperar, que de la información en este capítulo, usted puede ver
  553. la flexibilidad de este componente en particular y cómo puede darle
  554. forma a su aplicaciones o a las necesidades de su sitio web.
  555. </para>
  556. </sect2>
  557. </sect1>
  558. <!--
  559. vim:se ts=4 sw=4 et:
  560. -->