Zend_Form-Advanced.xml 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- EN-Revision: 17987 -->
  3. <!-- Reviewed: no -->
  4. <sect1 id="zend.form.advanced">
  5. <title>Uso avanzado de Zend_Form</title>
  6. <para>
  7. <classname>Zend_Form</classname>
  8. tiene una funcional riqueza, muchas de
  9. ellas dirigidas a expertos desarroladores. Este
  10. capítulo esta dirigido a
  11. documentar algunas de las funcionalidades con ejemplos y casos de
  12. uso.
  13. </para>
  14. <sect2 id="zend.form.advanced.arrayNotation">
  15. <title>Notación de array</title>
  16. <para>A muchos desarroladores web experimentados les gusta agrupar
  17. elementos relacionados de
  18. formulario usando notación de array en los
  19. nombres del elemento. Por ejemplo, si se
  20. tienen dos direcciones que
  21. se desean capturar, un envío y una dirección de facturación,
  22. se
  23. pueden tener elementos idénticos; agrupándolos en un array se puede
  24. asegurar que son
  25. capturados por separado. Nótese el siguiente
  26. formulario por ejemplo:</para>
  27. <programlisting language="html"><![CDATA[
  28. <form>
  29. <fieldset>
  30. <legend>Shipping Address</legend>
  31. <dl>
  32. <dt><label for="recipient">Ship to:</label></dt>
  33. <dd><input name="recipient" type="text" value="" /></dd>
  34. <dt><label for="address">Address:</label></dt>
  35. <dd><input name="address" type="text" value="" /></dd>
  36. <dt><label for="municipality">City:</label></dt>
  37. <dd><input name="municipality" type="text" value="" /></dd>
  38. <dt><label for="province">State:</label></dt>
  39. <dd><input name="province" type="text" value="" /></dd>
  40. <dt><label for="postal">Postal Code:</label></dt>
  41. <dd><input name="postal" type="text" value="" /></dd>
  42. </dl>
  43. </fieldset>
  44. <fieldset>
  45. <legend>Billing Address</legend>
  46. <dl>
  47. <dt><label for="payer">Bill To:</label></dt>
  48. <dd><input name="payer" type="text" value="" /></dd>
  49. <dt><label for="address">Address:</label></dt>
  50. <dd><input name="address" type="text" value="" /></dd>
  51. <dt><label for="municipality">City:</label></dt>
  52. <dd><input name="municipality" type="text" value="" /></dd>
  53. <dt><label for="province">State:</label></dt>
  54. <dd><input name="province" type="text" value="" /></dd>
  55. <dt><label for="postal">Postal Code:</label></dt>
  56. <dd><input name="postal" type="text" value="" /></dd>
  57. </dl>
  58. </fieldset>
  59. <dl>
  60. <dt><label for="terms">I agree to the Terms of Service</label></dt>
  61. <dd><input name="terms" type="checkbox" value="" /></dd>
  62. <dt></dt>
  63. <dd><input name="save" type="submit" value="Save" /></dd>
  64. </dl>
  65. </form>
  66. ]]></programlisting>
  67. <para>En este ejemplo, la facturación y la dirección de envío contienen
  68. algunos campos
  69. idénticos, eso significa que uno puede sobrescribir
  70. al otro. Nosotros podemos resolver
  71. esta solución usando una notación
  72. de array:</para>
  73. <programlisting language="html"><![CDATA[
  74. <form>
  75. <fieldset>
  76. <legend>Shipping Address</legend>
  77. <dl>
  78. <dt><label for="shipping-recipient">Ship to:</label></dt>
  79. <dd><input name="shipping[recipient]" id="shipping-recipient"
  80. type="text" value="" /></dd>
  81. <dt><label for="shipping-address">Address:</label></dt>
  82. <dd><input name="shipping[address]" id="shipping-address"
  83. type="text" value="" /></dd>
  84. <dt><label for="shipping-municipality">City:</label></dt>
  85. <dd><input name="shipping[municipality]" id="shipping-municipality"
  86. type="text" value="" /></dd>
  87. <dt><label for="shipping-province">State:</label></dt>
  88. <dd><input name="shipping[province]" id="shipping-province"
  89. type="text" value="" /></dd>
  90. <dt><label for="shipping-postal">Postal Code:</label></dt>
  91. <dd><input name="shipping[postal]" id="shipping-postal"
  92. type="text" value="" /></dd>
  93. </dl>
  94. </fieldset>
  95. <fieldset>
  96. <legend>Billing Address</legend>
  97. <dl>
  98. <dt><label for="billing-payer">Bill To:</label></dt>
  99. <dd><input name="billing[payer]" id="billing-payer"
  100. type="text" value="" /></dd>
  101. <dt><label for="billing-address">Address:</label></dt>
  102. <dd><input name="billing[address]" id="billing-address"
  103. type="text" value="" /></dd>
  104. <dt><label for="billing-municipality">City:</label></dt>
  105. <dd><input name="billing[municipality]" id="billing-municipality"
  106. type="text" value="" /></dd>
  107. <dt><label for="billing-province">State:</label></dt>
  108. <dd><input name="billing[province]" id="billing-province"
  109. type="text" value="" /></dd>
  110. <dt><label for="billing-postal">Postal Code:</label></dt>
  111. <dd><input name="billing[postal]" id="billing-postal"
  112. type="text" value="" /></dd>
  113. </dl>
  114. </fieldset>
  115. <dl>
  116. <dt><label for="terms">I agree to the Terms of Service</label></dt>
  117. <dd><input name="terms" type="checkbox" value="" /></dd>
  118. <dt></dt>
  119. <dd><input name="save" type="submit" value="Save" /></dd>
  120. </dl>
  121. </form>
  122. ]]></programlisting>
  123. <para>En el ejemplo anterior, obtenemos direcciones separadas. En el
  124. formulario sometido,
  125. ahora tenemos tres elementos, 'guardar'
  126. elemento para someterlo, y dos arrays, 'envio' y
  127. 'cuenta', cada uno
  128. con llaves para los variados elementos.</para>
  129. <para>
  130. <classname>Zend_Form</classname>
  131. intenta automatizar este proceso
  132. con los
  133. <link linkend="zend.form.forms.subforms">subformularios</link>
  134. . Por defecto, los subformularios son
  135. generados usando la notación de array como se
  136. muestra en el anterior
  137. formulario
  138. <acronym>HTML</acronym>
  139. listado completo con identificadores. El nombre del
  140. array esta basado en el nombre del
  141. subformulario, con las llaves
  142. basados en los elementos contenidos en el subformulario.
  143. Los
  144. subformularios pueder ser anidados arbitrariamente, y esto puede
  145. crear arrays anidados
  146. que reflejan la estructura. Adicionalmente,
  147. las validaciones rutinarias en
  148. <classname>Zend_Form</classname>
  149. respetan la estructura del array, asegurando que sus formularios
  150. sean validados
  151. correctamente, no importa cuan arbitrariamente
  152. anidados esten los subformularios. No se
  153. necesita hacer nada para
  154. beneficiarse; éste comportamiento esta activo por defecto.
  155. </para>
  156. <para>Adicionalmente, existen facilidades que le permiten activar
  157. condicionalmente la
  158. notación de un array, así como también
  159. especificar el específico array al cual un
  160. elemento o coleccion
  161. pertenece:</para>
  162. <itemizedlist>
  163. <listitem>
  164. <para>
  165. <methodname>Zend_Form::setIsArray($flag)</methodname>
  166. :
  167. Definiendo la bandera a verdadero, se puede indicar que un
  168. formulario entero
  169. debería ser tratado como un array. Por
  170. defecto, el nombre del formulario será
  171. usado como el nombre
  172. del array, a no ser que
  173. <methodname>setElementsBelongTo()</methodname>
  174. haya sido
  175. llamado. Si el formulario no tiene un nombre específico, o
  176. si
  177. <methodname>setElementsBelongTo()</methodname>
  178. no ha sido
  179. definido, esta bandera será ignorada (como cuando no hay
  180. nombre del
  181. array al cual los elementos puedan pertenecer).
  182. </para>
  183. <para>
  184. Se deberá determinar si un formulario está siendo tratado
  185. como un array usando el
  186. accesor
  187. <methodname>isArray()</methodname>
  188. .
  189. </para>
  190. </listitem>
  191. <listitem>
  192. <para>
  193. <methodname>Zend_Form::setElementsBelongTo($array)</methodname>
  194. :
  195. Usando este método, se puede especificar el nombre de un
  196. array al cual todos los
  197. elementos del formulario pertenecen.
  198. Se puede determinar el nombre usando el
  199. accesor
  200. <methodname>getElementsBelongTo()</methodname>
  201. .
  202. </para>
  203. </listitem>
  204. </itemizedlist>
  205. <para>
  206. Adicionalmente, a nivel del elemento, se pueden especificar
  207. elementos individuales que
  208. puedan pertenecer a arrays particulares
  209. usando el método
  210. <methodname>Zend_Form_Element::setBelongsTo()</methodname>
  211. . Para
  212. descubrir el valor que tiene -- sea o no sea definido explícitamente
  213. o
  214. implícitamente a través del formulario -- se puede usar el accesor
  215. <methodname>getBelongsTo()</methodname>
  216. .
  217. </para>
  218. </sect2>
  219. <sect2 id="zend.form.advanced.multiPage">
  220. <title>Formularios Multi-Página</title>
  221. <para>
  222. Actualmente, los formularios multi-página no están oficialmente
  223. soportados en
  224. <classname>Zend_Form</classname>
  225. ; sin embargo, la
  226. mayoría del soporte para implementarlos está disponible y puede ser
  227. utilizado con algunos retoques.
  228. </para>
  229. <para>La clave para crear fomrularios multi-página es utilizar
  230. subformularios, pero solo para
  231. mostrar un solo subformulario por
  232. página. Esto le permite someter un solo subformulario a
  233. la vez y
  234. validarlo, pero no procesar el formulario hasta que todos los
  235. subformularios
  236. esten completos.</para>
  237. <example id="zend.form.advanced.multiPage.registration">
  238. <title>Ejemplo de formulario de registro</title>
  239. <para>Vamos a usar un formulario de registro como ejemplo. Para
  240. nuestros propósitos,
  241. queremos capturar el nombre del usuario y
  242. la contraseña en la primera página, después
  243. la información del
  244. usuario -- nombre, apellido, y ubicación -- y finalmente
  245. permitirles decidir qué lista de correo, si desean suscribirse.</para>
  246. <para>Primero, vamos a crear nuestro propio formulario, y definir
  247. varios subformularios
  248. dentro del mismo:</para>
  249. <programlisting language="php"><![CDATA[
  250. class My_Form_Registration extends Zend_Form
  251. {
  252. public function init()
  253. {
  254. // Crea un subformulario usuario: username y password
  255. $user = new Zend_Form_SubForm();
  256. $user->addElements(array(
  257. new Zend_Form_Element_Text('username', array(
  258. 'required' => true,
  259. 'label' => 'Username:',
  260. 'filters' => array('StringTrim', 'StringToLower'),
  261. 'validators' => array(
  262. 'Alnum',
  263. array('Regex',
  264. false,
  265. array('/^[a-z][a-z0-9]{2,}$/'))
  266. )
  267. )),
  268. new Zend_Form_Element_Password('password', array(
  269. 'required' => true,
  270. 'label' => 'Password:',
  271. 'filters' => array('StringTrim'),
  272. 'validators' => array(
  273. 'NotEmpty',
  274. array('StringLength', false, array(6))
  275. )
  276. )),
  277. ));
  278. // Crea un subformulario de datos demográficos : given name, family name, y
  279. // location
  280. $demog = new Zend_Form_SubForm();
  281. $demog->addElements(array(
  282. new Zend_Form_Element_Text('givenName', array(
  283. 'required' => true,
  284. 'label' => 'Given (First) Name:',
  285. 'filters' => array('StringTrim'),
  286. 'validators' => array(
  287. array('Regex',
  288. false,
  289. array('/^[a-z][a-z0-9., \'-]{2,}$/i'))
  290. )
  291. )),
  292. new Zend_Form_Element_Text('familyName', array(
  293. 'required' => true,
  294. 'label' => 'Family (Last) Name:',
  295. 'filters' => array('StringTrim'),
  296. 'validators' => array(
  297. array('Regex',
  298. false,
  299. array('/^[a-z][a-z0-9., \'-]{2,}$/i'))
  300. )
  301. )),
  302. new Zend_Form_Element_Text('location', array(
  303. 'required' => true,
  304. 'label' => 'Your Location:',
  305. 'filters' => array('StringTrim'),
  306. 'validators' => array(
  307. array('StringLength', false, array(2))
  308. )
  309. )),
  310. ));
  311. // Crea un sub fomulario de correos
  312. $listOptions = array(
  313. 'none' => 'No lists, please',
  314. 'fw-general' => 'Zend Framework General List',
  315. 'fw-mvc' => 'Zend Framework MVC List',
  316. 'fw-auth' => 'Zend Framwork Authentication and ACL List',
  317. 'fw-services' => 'Zend Framework Web Services List',
  318. );
  319. $lists = new Zend_Form_SubForm();
  320. $lists->addElements(array(
  321. new Zend_Form_Element_MultiCheckbox('subscriptions', array(
  322. 'label' =>
  323. 'Which lists would you like to subscribe to?',
  324. 'multiOptions' => $listOptions,
  325. 'required' => true,
  326. 'filters' => array('StringTrim'),
  327. 'validators' => array(
  328. array('InArray',
  329. false,
  330. array(array_keys($listOptions)))
  331. )
  332. )),
  333. ));
  334. // Adjuntando los subformlarios al formulario principal
  335. $this->addSubForms(array(
  336. 'user' => $user,
  337. 'demog' => $demog,
  338. 'lists' => $lists
  339. ));
  340. }
  341. }
  342. ]]></programlisting>
  343. <para>Note que no hay botones de enviar, y que ni hemos hecho nada
  344. con los decoradores de
  345. subformularios -- lo que significa que
  346. por defecto serán desplegados como campos.
  347. Necesitaremos hacer
  348. algo con ellos mientras desplegamos cada subformulario
  349. individualmente, y añadir botones de manera que podamos
  350. procesarlos realmente -- el
  351. cual requerira las propiedades
  352. acción y método. Vamos a añadir algunos andamios a
  353. nuestras
  354. clases para proveer esa información:</para>
  355. <programlisting language="php"><![CDATA[
  356. class My_Form_Registration extends Zend_Form
  357. {
  358. // ...
  359. /**
  360. * Prepara un subformulario para mostrar
  361. *
  362. * @param string|Zend_Form_SubForm $spec
  363. * @return Zend_Form_SubForm
  364. */
  365. public function prepareSubForm($spec)
  366. {
  367. if (is_string($spec)) {
  368. $subForm = $this->{$spec};
  369. } elseif ($spec instanceof Zend_Form_SubForm) {
  370. $subForm = $spec;
  371. } else {
  372. throw new Exception('Invalid argument passed to ' .
  373. __FUNCTION__ . '()');
  374. }
  375. $this->setSubFormDecorators($subForm)
  376. ->addSubmitButton($subForm)
  377. ->addSubFormActions($subForm);
  378. return $subForm;
  379. }
  380. /**
  381. * Add form decorators to an individual sub form
  382. *
  383. * @param Zend_Form_SubForm $subForm
  384. * @return My_Form_Registration
  385. */
  386. public function setSubFormDecorators(Zend_Form_SubForm $subForm)
  387. {
  388. $subForm->setDecorators(array(
  389. 'FormElements',
  390. array('HtmlTag', array('tag' => 'dl',
  391. 'class' => 'zend_form')),
  392. 'Form',
  393. ));
  394. return $this;
  395. }
  396. /**
  397. * Añade un Boton de envio(submit) a cada subformulario
  398. *
  399. * @param Zend_Form_SubForm $subForm
  400. * @return My_Form_Registration
  401. */
  402. public function addSubmitButton(Zend_Form_SubForm $subForm)
  403. {
  404. $subForm->addElement(new Zend_Form_Element_Submit(
  405. 'save',
  406. array(
  407. 'label' => 'Save and continue',
  408. 'required' => false,
  409. 'ignore' => true,
  410. )
  411. ));
  412. return $this;
  413. }
  414. /**
  415. * Añade el method y el action a cada subformulario
  416. *
  417. * @param Zend_Form_SubForm $subForm
  418. * @return My_Form_Registration
  419. */
  420. public function addSubFormActions(Zend_Form_SubForm $subForm)
  421. {
  422. $subForm->setAction('/registration/process')
  423. ->setMethod('post');
  424. return $this;
  425. }
  426. }
  427. ]]></programlisting>
  428. <para>
  429. Siguiente, necesitamos añadir andamios a nuestro action
  430. controller, y tener varias
  431. consideraciones. Primero, necesitamos
  432. asegurar que persiste la información del
  433. formulario entre los
  434. requerimientos, de esa manera determinar cuándo terminar.
  435. Segundo, necesitamos alguna lógica para determinar qué segmentos
  436. del formulario han
  437. sido sometidos, y qué subformulario mostrar
  438. de acuerdo a la información. Usaremos
  439. <classname>Zend_Session_Namespace</classname>
  440. para persistir
  441. la información, el cual nos ayudará a responder la pregunta de
  442. qué
  443. formulario someter.
  444. </para>
  445. <para>Vamos a crear nuestro controlador, y añadir un método para
  446. recuperar un formulario
  447. instanciado:</para>
  448. <programlisting language="php"><![CDATA[
  449. class RegistrationController extends Zend_Controller_Action
  450. {
  451. protected $_form;
  452. public function getForm()
  453. {
  454. if (null === $this->_form) {
  455. $this->_form = new My_Form_Registration();
  456. }
  457. return $this->_form;
  458. }
  459. }
  460. ]]></programlisting>
  461. <para>Ahora, vamos a añadir algunas funcionalidades para determinar
  462. qué formulario
  463. mostrar. Básicamente, hasta que el formulario
  464. entero sea considerado válido,
  465. necesitamos continuar mostrando
  466. segmentos de formulario. Adicionalmente, queremos
  467. asegurar que
  468. están en un orden particular: usuario, demog, y después las
  469. listas.
  470. Podemos determinar qué información ha sido sometida
  471. verificando nuestro session
  472. namespace para claves particulares
  473. representando cada subformulario.</para>
  474. <programlisting language="php"><![CDATA[
  475. class RegistrationController extends Zend_Controller_Action
  476. {
  477. // ...
  478. protected $_namespace = 'RegistrationController';
  479. protected $_session;
  480. /**
  481. * Obtiene el namespace de la sesión que estamos usando
  482. *
  483. * @return Zend_Session_Namespace
  484. */
  485. public function getSessionNamespace()
  486. {
  487. if (null === $this->_session) {
  488. $this->_session =
  489. new Zend_Session_Namespace($this->_namespace);
  490. }
  491. return $this->_session;
  492. }
  493. /**
  494. * Obtiene la lista de Formularios que ya están almacenados en la sesión
  495. *
  496. * @return array
  497. */
  498. public function getStoredForms()
  499. {
  500. $stored = array();
  501. foreach ($this->getSessionNamespace() as $key => $value) {
  502. $stored[] = $key;
  503. }
  504. return $stored;
  505. }
  506. /**
  507. * Obtiene la lista de todos los subformularios disponibles
  508. *
  509. * @return array
  510. */
  511. public function getPotentialForms()
  512. {
  513. return array_keys($this->getForm()->getSubForms());
  514. }
  515. /**
  516. * ¿Qué subformulario se envio?
  517. *
  518. * @return false|Zend_Form_SubForm
  519. */
  520. public function getCurrentSubForm()
  521. {
  522. $request = $this->getRequest();
  523. if (!$request->isPost()) {
  524. return false;
  525. }
  526. foreach ($this->getPotentialForms() as $name) {
  527. if ($data = $request->getPost($name, false)) {
  528. if (is_array($data)) {
  529. return $this->getForm()->getSubForm($name);
  530. break;
  531. }
  532. }
  533. }
  534. return false;
  535. }
  536. /**
  537. * Obtiene el siguiente subformulario para mostrarlo
  538. *
  539. * @return Zend_Form_SubForm|false
  540. */
  541. public function getNextSubForm()
  542. {
  543. $storedForms = $this->getStoredForms();
  544. $potentialForms = $this->getPotentialForms();
  545. foreach ($potentialForms as $name) {
  546. if (!in_array($name, $storedForms)) {
  547. return $this->getForm()->getSubForm($name);
  548. }
  549. }
  550. return false;
  551. }
  552. }
  553. ]]></programlisting>
  554. <para>
  555. El método de arriba nos permite usar notaciones tal como
  556. "
  557. <command>$subForm =
  558. $this-&gt;getCurrentSubForm();</command>
  559. " recuperar
  560. el actual subformulario para la validación, o "
  561. <command>$next
  562. = $this-&gt;getNextSubForm();</command>
  563. " obtener el
  564. siguiente para mostrar.
  565. </para>
  566. <para>
  567. Ahora, vamos a encontrar la manera para procesar y mostrar
  568. varios subformularios.
  569. Podemos usar
  570. <methodname>getCurrentSubForm()</methodname>
  571. para determinar
  572. si algún subformulario ha sido sometido (los valores de retorno
  573. falso
  574. indican que ninguno ha sido desplegado o sometido), y
  575. <methodname>getNextSubForm()</methodname>
  576. recupera el
  577. formulario que mostrar. Podemos entonces usar el método del
  578. formulario
  579. <methodname>prepareSubForm()</methodname>
  580. para
  581. asegurar que el formulario está listo para mostrar.
  582. </para>
  583. <para>Cuando tenemos un formulario sometido, podemos validar el
  584. subformulario, y luego
  585. verificar si el formulario entero es
  586. válido ahora. Para hacer esas tareas,
  587. necesitamos métodos
  588. adicionales que aseguren que la información sometida es añadida
  589. a
  590. la sesión, y que cuando validamos el formulario entero,
  591. nosotros validamos contra
  592. todos los segmentos de la sesión:</para>
  593. <programlisting language="php"><![CDATA[
  594. class RegistrationController extends Zend_Controller_Action
  595. {
  596. // ...
  597. /**
  598. * ¿Es válido el subformulario?
  599. *
  600. * @param Zend_Form_SubForm $subForm
  601. * @param array $data
  602. * @return bool
  603. */
  604. public function subFormIsValid(Zend_Form_SubForm $subForm,
  605. array $data)
  606. {
  607. $name = $subForm->getName();
  608. if ($subForm->isValid($data)) {
  609. $this->getSessionNamespace()->$name = $subForm->getValues();
  610. return true;
  611. }
  612. return false;
  613. }
  614. /**
  615. * ¿Es válido todo el formulario?
  616. *
  617. * @return bool
  618. */
  619. public function formIsValid()
  620. {
  621. $data = array();
  622. foreach ($this->getSessionNamespace() as $key => $info) {
  623. $data[$key] = $info;
  624. }
  625. return $this->getForm()->isValid($data);
  626. }
  627. }
  628. ]]></programlisting>
  629. <para>Ahora que tenemos el trabajo preparado, vamos a construir las
  630. acciones para este
  631. controlador. Necesitaremos una página de
  632. destino para el formulario, y luego una
  633. acción 'process' para
  634. procesar el formulario.</para>
  635. <programlisting language="php"><![CDATA[
  636. class RegistrationController extends Zend_Controller_Action
  637. {
  638. // ...
  639. public function indexAction()
  640. {
  641. // volver a mostrar la página actual, o mostrar el "siguiente"
  642. // (primer) subformulario
  643. if (!$form = $this->getCurrentSubForm()) {
  644. $form = $this->getNextSubForm();
  645. }
  646. $this->view->form = $this->getForm()->prepareSubForm($form);
  647. }
  648. public function processAction()
  649. {
  650. if (!$form = $this->getCurrentSubForm()) {
  651. return $this->_forward('index');
  652. }
  653. if (!$this->subFormIsValid($form,
  654. $this->getRequest()->getPost())) {
  655. $this->view->form = $this->getForm()->prepareSubForm($form);
  656. return $this->render('index');
  657. }
  658. if (!$this->formIsValid()) {
  659. $form = $this->getNextSubForm();
  660. $this->view->form = $this->getForm()->prepareSubForm($form);
  661. return $this->render('index');
  662. }
  663. // Formulario Válido!
  664. // Render information in a verification page
  665. $this->view->info = $this->getSessionNamespace();
  666. $this->render('verification');
  667. }
  668. }
  669. ]]></programlisting>
  670. <para>Como se ha notado, el código actual para procesar el
  671. formulario es relativamente
  672. simple. Verificamos si tenemos un
  673. subformulario actual sometido y si no, retornamos a
  674. la página de
  675. destino. Si tenemos un subformulario, intentaremos validarlo,
  676. volviéndolo a mostrar si tiene fallos. Si el subformulario es
  677. válido, entonces
  678. verificaremos si el formulario es válido, lo
  679. que debería indicar que hemos terminado;
  680. si no, mostraremos el
  681. siguiente segmento del formulario. Finalmente, mostraremos una
  682. página de verificación con el contenido de la sesión.</para>
  683. <para>Los scripts de vista son muy simples:</para>
  684. <programlisting language="php"><![CDATA[
  685. <?php // registration/index.phtml ?>
  686. <h2>registro</h2>
  687. <?php echo $this->form ?>
  688. <?php // registration/verification.phtml ?>
  689. <h2>Gracias por Registrarse!</h2>
  690. <p>
  691. Aquí está la información que nos ha proporcionado:
  692. </p>
  693. <?php
  694. // Tienen que construir esto con los items que estan almacenados en los namespaces
  695. // de la sesión
  696. foreach ($this->info as $info):
  697. foreach ($info as $form => $data): ?>
  698. <h4><?php echo ucfirst($form) ?>:</h4>
  699. <dl>
  700. <?php foreach ($data as $key => $value): ?>
  701. <dt><?php echo ucfirst($key) ?></dt>
  702. <?php if (is_array($value)):
  703. foreach ($value as $label => $val): ?>
  704. <dd><?php echo $val ?></dd>
  705. <?php endforeach;
  706. else: ?>
  707. <dd><?php echo $this->escape($value) ?></dd>
  708. <?php endif;
  709. endforeach; ?>
  710. </dl>
  711. <?php endforeach;
  712. endforeach
  713. ]]></programlisting>
  714. <para>Próximas novedades de Zend Framework incluirán componentes
  715. para hacer formularios
  716. multi páginas mas simples, abstrayendo la
  717. sesión y la lógica de orden. Mientras
  718. tanto, el ejemplo de
  719. arriba debería servir como guia razonable para alcanzar esta
  720. tarea en su web.</para>
  721. </example>
  722. </sect2>
  723. </sect1>