<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Dr. Danguer y Mr. Daniel &#187; Zend Framework</title>
	<atom:link href="http://vida.danguer.com/tag/zend-framework/feed/" rel="self" type="application/rss+xml" />
	<link>http://vida.danguer.com</link>
	<description>Un blog más de un freelancer</description>
	<lastBuildDate>Wed, 26 Oct 2011 15:54:05 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Cuidado al usar Zend_Date</title>
		<link>http://vida.danguer.com/2010/01/30/cuidado-al-usar-zend_date/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=cuidado-al-usar-zend_date</link>
		<comments>http://vida.danguer.com/2010/01/30/cuidado-al-usar-zend_date/#comments</comments>
		<pubDate>Sun, 31 Jan 2010 00:14:20 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Trabajo]]></category>
		<category><![CDATA[Fechas]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[Zend_Date]]></category>

		<guid isPermaLink="false">http://vida.danguer.com/?p=96</guid>
		<description><![CDATA[<a href="http://vida.danguer.com/2010/01/30/cuidado-al-usar-zend_date/" title="Cuidado al usar Zend_Date"></a><p>En un proyecto, estaba utilizando Zend_Date para manejo de horas en diferentes zonas horarias, cuando lo estaba desarrollando empecé a tener un error porque olvidé que la fecha se actualiza cuando cambias un parámetro y el problema surge cuando cambias el mes o día y se encuentra con una fecha inexistente aunque en el código parezca correcta, por ejemplo, supongamos que estamos en el mes de febrero y queremos crear una fecha de marzo (asignaré la fecha para reproducir el error, aunque el error es cuando se utiliza la fecha actual)</p>
<pre name="code" class="php">include_once("Zend/Date.php");
$fecha_febrero = mktime(0, 0, 0, 2, 1, 2010);
$fecha = new Zend_Date($fecha_febrero);
$fecha-&#62;setDay(31);
$fecha-&#62;setMonth(3);
print "Fecha Marzo: ".date("d/m/Y", $fecha-&#62;getTimestamp());</pre>
<p>Uno esperaría que el resultado fuera: <strong>31/03/2010</strong></p>
<p>Pero en su lugar mostrará <strong>03/03/2010</strong></p>
<p>Esto es porque al hacer <code>$fecha-&#62;setDay(31)</code> el sistema intenta crear la fecha: <strong>31/02/2010</strong> que no existe, por lo que &#8220;recorre&#8221; los días restantes para quedar en <strong>03/03/2010</strong>, al asignar el mes, no tiene efecto.</p>
<p>La solución es simplemente hacerlo en orden inverso:</p>
<pre name="code" class="php">include_once("Zend/Date.php");
$fecha_febrero = mktime(0, 0, 0, 2, 1, 2010);
$fecha = new Zend_Date($fecha_febrero);
$fecha-&#62;setMonth(3);
$fecha-&#62;setDay(31);
print "Fecha Marzo: ".date("d/m/Y", $fecha-&#62;getTimestamp());</pre>
<p>Eso parecería la solución ideal (y es la recomendada por la documentación), pero no es totalmente cierta, si por ejemplo estamos en enero 31 del 2010 e intentamos asignar una fecha de febrero, siempre obtendremos una fecha de marzo:</p>
<pre name="code" class="php">include_once 'Zend/Date.php';
$fecha_enero = mktime(0, 0, 0, 1, 31, 2010);
$fecha = new Zend_Date($fecha_enero);
$fecha-&#62;setMonth(2);
$fecha-&#62;setDay(10);
print "Fecha Febrero: ".date("d/m/Y", $fecha-&#62;getTimestamp());</pre>
<p>Uno esperaría que mostrara la fecha:<br />
<strong>10/02/2010</strong></p>
<p>Pero en realidad muestra<br />
<strong>10/03/2010</strong></p>
<p>Esto porque cuando asignamos el mes, el sistema intenta crear la fecha 31/03/2010 que una vez más es incorrecta, por lo que crea la fecha 03/03/2010, pero al asignar la fecha, el resultado es&#8230;</p>]]></description>
			<content:encoded><![CDATA[<a href="http://vida.danguer.com/2010/01/30/cuidado-al-usar-zend_date/" title="Cuidado al usar Zend_Date"></a><p>En un proyecto, estaba utilizando Zend_Date para manejo de horas en diferentes zonas horarias, cuando lo estaba desarrollando empecé a tener un error porque olvidé que la fecha se actualiza cuando cambias un parámetro y el problema surge cuando cambias el mes o día y se encuentra con una fecha inexistente aunque en el código parezca correcta, por ejemplo, supongamos que estamos en el mes de febrero y queremos crear una fecha de marzo (asignaré la fecha para reproducir el error, aunque el error es cuando se utiliza la fecha actual)</p>
<pre name="code" class="php">include_once("Zend/Date.php");
$fecha_febrero = mktime(0, 0, 0, 2, 1, 2010);
$fecha = new Zend_Date($fecha_febrero);
$fecha-&gt;setDay(31);
$fecha-&gt;setMonth(3);
print "Fecha Marzo: ".date("d/m/Y", $fecha-&gt;getTimestamp());</pre>
<p>Uno esperaría que el resultado fuera: <strong>31/03/2010</strong></p>
<p>Pero en su lugar mostrará <strong>03/03/2010</strong></p>
<p>Esto es porque al hacer <code>$fecha-&gt;setDay(31)</code> el sistema intenta crear la fecha: <strong>31/02/2010</strong> que no existe, por lo que &#8220;recorre&#8221; los días restantes para quedar en <strong>03/03/2010</strong>, al asignar el mes, no tiene efecto.</p>
<p>La solución es simplemente hacerlo en orden inverso:</p>
<pre name="code" class="php">include_once("Zend/Date.php");
$fecha_febrero = mktime(0, 0, 0, 2, 1, 2010);
$fecha = new Zend_Date($fecha_febrero);
$fecha-&gt;setMonth(3);
$fecha-&gt;setDay(31);
print "Fecha Marzo: ".date("d/m/Y", $fecha-&gt;getTimestamp());</pre>
<p>Eso parecería la solución ideal (y es la recomendada por la documentación), pero no es totalmente cierta, si por ejemplo estamos en enero 31 del 2010 e intentamos asignar una fecha de febrero, siempre obtendremos una fecha de marzo:</p>
<pre name="code" class="php">include_once 'Zend/Date.php';
$fecha_enero = mktime(0, 0, 0, 1, 31, 2010);
$fecha = new Zend_Date($fecha_enero);
$fecha-&gt;setMonth(2);
$fecha-&gt;setDay(10);
print "Fecha Febrero: ".date("d/m/Y", $fecha-&gt;getTimestamp());</pre>
<p>Uno esperaría que mostrara la fecha:<br />
<strong>10/02/2010</strong></p>
<p>Pero en realidad muestra<br />
<strong>10/03/2010</strong></p>
<p>Esto porque cuando asignamos el mes, el sistema intenta crear la fecha 31/03/2010 que una vez más es incorrecta, por lo que crea la fecha 03/03/2010, pero al asignar la fecha, el resultado es un error en el mes.</p>
<p>Aunque esto no es un error, es muy peligroso porque uno puede suponer que la fecha es correcta porque en el código lo parece, la solución sin embargo es trivial, asignar el primer día de un mes que tenga 31 días y asignar los valores en orden inverso (primero año, luego mes y por último día), así el código sin error sería:</p>
<pre name="code" class="php">
include_once 'Zend/Date.php';
$fecha = new Zend_Date(0, 0, 0, 1, 1, date('Y'));
$fecha-&gt;setMonth(2);
$fecha-&gt;setDay(10);
print "Fecha Febrero: ".date("d/m/Y", $fecha-&gt;getTimestamp());
</pre>
<p>Resultado (el esperado)<br />
<strong>10/02/2010</strong></p>
<p>Esto funciona en la mayoría de los casos; aunque si van a manejar diferentes zonas horarias mediante <code>setTimezone()</code> el código anterior tendrá el mismo error en los casos que la zona horaria sea menor a la zona horaria del servidor, por lo que hay que hacer algo más elaborado:</p>
<pre name="code" class="php">
include_once 'Zend/Date.php';
$fecha = new Zend_Date();
//eliminar "errores"
$fecha-&gt;setTimezone('mi_codigo_zona_horaria');
$fecha-&gt;setDay(1);
$fecha-&gt;setMonth(1);

//nuestro código
$fecha-&gt;setMonth(2);
$fecha-&gt;setDay(10);
print "Fecha Febrero: ".date("d/m/Y", $fecha-&gt;getTimestamp());
</pre>
<p>Lo peligroso del comportamiento de Zend_Date es que funcionará con errores durante algunos días/meses dependiendo de la manera en como se programe y es un poco difícil de diagnosticar por su misma naturaleza, con esto se elimina cualquier tipo de errores.</p>
]]></content:encoded>
			<wfw:commentRss>http://vida.danguer.com/2010/01/30/cuidado-al-usar-zend_date/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Certificación en Zend Framework</title>
		<link>http://vida.danguer.com/2008/10/08/certificacion-en-zend-framework/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=certificacion-en-zend-framework</link>
		<comments>http://vida.danguer.com/2008/10/08/certificacion-en-zend-framework/#comments</comments>
		<pubDate>Wed, 08 Oct 2008 15:24:34 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Trabajo]]></category>
		<category><![CDATA[Zend]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://vida.danguer.com/?p=76</guid>
		<description><![CDATA[<a href="http://vida.danguer.com/2008/10/08/certificacion-en-zend-framework/" title="Certificación en Zend Framework"></a><p>Hace poco Zend publicó la certificación de Zend Framework:<br />
<a href="http://www.zend.com/en/services/certification/framework/">http://www.zend.com/en/services/certification/framework/</a></p>
<p>Estoy algo divergente entre si es una buena opción o no</p>
<p>Buena opción:</p>
<ul>
<li>El Framework está muy bien hecho como para que valga una certificación</li>
<li>Tiene tantos componentes que es una buena medida para destacar entre los que han utilizado solamente brevemente el Framework</li>
</ul>
<p> </p>
<p>Mala opción</p>
<ul>
<li>Cuesta más que la certificación en PHP ($160 dolares en contra de $125 para la certificación de PHP)</li>
<li>Lamentablemente la certificación es en la versión 1.5 y la versión estable es la versión 1.6, si bien la versión 1.5 ya tenía muy estandarizado el modelo del Framework, a menos que tengan un periodo largo de liberar versiones (lo cual puede ser malo ya que ahora hay mucho movimiento) en menos de un año seguramente saldran al menos un par de versiones por lo que ¿se va a certificar en cada version? =P</li>
</ul>
<div>Tampoco hay guia oficial, solamente está la opción de curso.</div>
<div></div>
<div>Creo que el Zend Framework debe crecer un poco más para estabilizarse en cuestión de características generales y de ahi ya es una opción muy válida de certificación; ya que en el momento hay mucho movimiento en cuestión de nuevas características, por ejemplo la versión 1.6 la principal mejora fue la introducción de Dojo.</div>
<p> </p>
]]></description>
			<content:encoded><![CDATA[<a href="http://vida.danguer.com/2008/10/08/certificacion-en-zend-framework/" title="Certificación en Zend Framework"></a><p>Hace poco Zend publicó la certificación de Zend Framework:<br />
<a href="http://www.zend.com/en/services/certification/framework/">http://www.zend.com/en/services/certification/framework/</a></p>
<p>Estoy algo divergente entre si es una buena opción o no</p>
<p>Buena opción:</p>
<ul>
<li>El Framework está muy bien hecho como para que valga una certificación</li>
<li>Tiene tantos componentes que es una buena medida para destacar entre los que han utilizado solamente brevemente el Framework</li>
</ul>
<p> </p>
<p>Mala opción</p>
<ul>
<li>Cuesta más que la certificación en PHP ($160 dolares en contra de $125 para la certificación de PHP)</li>
<li>Lamentablemente la certificación es en la versión 1.5 y la versión estable es la versión 1.6, si bien la versión 1.5 ya tenía muy estandarizado el modelo del Framework, a menos que tengan un periodo largo de liberar versiones (lo cual puede ser malo ya que ahora hay mucho movimiento) en menos de un año seguramente saldran al menos un par de versiones por lo que ¿se va a certificar en cada version? =P</li>
</ul>
<div>Tampoco hay guia oficial, solamente está la opción de curso.</div>
<div></div>
<div>Creo que el Zend Framework debe crecer un poco más para estabilizarse en cuestión de características generales y de ahi ya es una opción muy válida de certificación; ya que en el momento hay mucho movimiento en cuestión de nuevas características, por ejemplo la versión 1.6 la principal mejora fue la introducción de Dojo.</div>
<p> </p>
]]></content:encoded>
			<wfw:commentRss>http://vida.danguer.com/2008/10/08/certificacion-en-zend-framework/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Actualización a Zend Framework 1.6</title>
		<link>http://vida.danguer.com/2008/09/05/actualizacion-a-zend-framework-16/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=actualizacion-a-zend-framework-16</link>
		<comments>http://vida.danguer.com/2008/09/05/actualizacion-a-zend-framework-16/#comments</comments>
		<pubDate>Fri, 05 Sep 2008 08:03:40 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Trabajo]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://vida.danguer.com/?p=55</guid>
		<description><![CDATA[<a href="http://vida.danguer.com/2008/09/05/actualizacion-a-zend-framework-16/" title="Actualización a Zend Framework 1.6"></a><p>Me acabo de dar cuenta que ya hay una nueva versión estable de Zend Framework, la 1.6.</p>
<p>Al parecer lo más novedoso es la incorporación de Dojo y la incorporación de SOAP. En lo particular no uso Dojo, pero vale la pena probar estos cambios.</p>
<p>No planeaba &#8220;actualizar&#8221; tan rápidamente, pero me acabo de dar cuenta que hay un bug en las versiones de 1.5.* que cuando Zend_Db lee un campo tipo LONGBLOB trata de reservar en una variable todo el tamaño máximo del longblob (aproximadamente 4GB) algo que hará tronar a PHP y marcará un fatal error.</p>
<p>Como estoy trabajando en un proyecto con LONGBLOB decidí actualizar, más adelante escribiré mis experiencias con los nuevos componentes, que SOAP es algo que tengo que probar =).</p>
<p><strong>Bug de Zend Framework</strong>:<a href="http://framework.zend.com/issues/browse/ZF-1498" target="_blank">http://framework.zend.com/issues/browse/ZF-1498</a></p>
<p><a title="Zend Framework - Version 1.6" href="http://framework.zend.com/download/latest" target="_blank">Descargar Zend Framework 1.6</a></p>
]]></description>
			<content:encoded><![CDATA[<a href="http://vida.danguer.com/2008/09/05/actualizacion-a-zend-framework-16/" title="Actualización a Zend Framework 1.6"></a><p>Me acabo de dar cuenta que ya hay una nueva versión estable de Zend Framework, la 1.6.</p>
<p>Al parecer lo más novedoso es la incorporación de Dojo y la incorporación de SOAP. En lo particular no uso Dojo, pero vale la pena probar estos cambios.</p>
<p>No planeaba &#8220;actualizar&#8221; tan rápidamente, pero me acabo de dar cuenta que hay un bug en las versiones de 1.5.* que cuando Zend_Db lee un campo tipo LONGBLOB trata de reservar en una variable todo el tamaño máximo del longblob (aproximadamente 4GB) algo que hará tronar a PHP y marcará un fatal error.</p>
<p>Como estoy trabajando en un proyecto con LONGBLOB decidí actualizar, más adelante escribiré mis experiencias con los nuevos componentes, que SOAP es algo que tengo que probar =).</p>
<p><strong>Bug de Zend Framework</strong>:<a href="http://framework.zend.com/issues/browse/ZF-1498" target="_blank">http://framework.zend.com/issues/browse/ZF-1498</a></p>
<p><a title="Zend Framework - Version 1.6" href="http://framework.zend.com/download/latest" target="_blank">Descargar Zend Framework 1.6</a></p>
]]></content:encoded>
			<wfw:commentRss>http://vida.danguer.com/2008/09/05/actualizacion-a-zend-framework-16/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MVC en Zend Framework</title>
		<link>http://vida.danguer.com/2008/09/01/mvc-en-zend-framework/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=mvc-en-zend-framework</link>
		<comments>http://vida.danguer.com/2008/09/01/mvc-en-zend-framework/#comments</comments>
		<pubDate>Mon, 01 Sep 2008 09:12:29 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://vida.danguer.com/?p=50</guid>
		<description><![CDATA[<a href="http://vida.danguer.com/2008/09/01/mvc-en-zend-framework/" title="MVC en Zend Framework"></a><p><a title="MVC - Modelo-Vista-Controlador Wikipedia" href="http://es.wikipedia.org/wiki/Modelo_Vista_Controlador" target="_blank">MVC</a> es un acrónimo para Model-View-Controller (Modelo-Vista-Controlador); esta es un patrón de arquitectura de software.</p>
<p>Básicamente este patrón divide una aplicación (en nuestro caso una aplicación web) en tres partes:</p>
<ul>
<li><strong>Modelo</strong><br />
Es la parte que se entenderá con la base de datos, una manera elegante y clara de separar esto, es que para cada tabla generar una clase que será su Modelo, aunque en realidad podría ser que un Modelo controle varias tablas que tengan mucho en común, por ejemplo para las relaciones muchos-a-muchos.</li>
<li><strong>Controlador</strong><br />
Se encarga de procesar la entrada del usuario, en nuestro caso de recoger los datos de formularios, la URL, etc. Procesarlos (utilizando los otros componentes ya que esta parte debería ser la única que se comunica con los demás y las otras partes deben estar aisladas) y producir un resultado.</li>
<li><strong>Vista</strong><br />
Es la parte que maneja la parte que el usuario verá, el caso más común es tener una página en HTML, pero las posibilidades son que podemos tener incluso páginas en WAP (contenido móbil) o representaciones de texto. El controlador procesará todo lo necesario y enviará sus resultados a la vista (en el caso de Zend Framework mediante asignación de variables). La vista procesará todos los datos de una manera que sean claros para el usuario (aunque una vez más, esto podría ser incluso tener como salida por ejemplo XML para una API para comunicación entre librerías)</li>
</ul>
<p>En este tutorial veremos de manera introductoria como funciona el patrón de MVC con Zend Framework. Antes de ver el código, mostraremos como funciona básicamente Zend Framework con MVC mediante el siguiente esquema:</p>
<p><img src="http://vida.danguer.com/archivos/articulos/Zend_MVC/MVC_Proceso.png" alt="Proceso de MVC en Zend Framework" width="530" height="510" /></p>
<p>En el esquema el primer paso es cuando accedemos a una dirección, por ejemplo <code>http://www.danguer.com/ajax/resultado</code></p>
<p>La configuración de Zend Framework mediante Apache utilizando <a title="Mod-Rewrite Apache Ingles" href="http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html" target="_blank">Mod_Rewrite</a> hace que&#8230;</p>]]></description>
			<content:encoded><![CDATA[<a href="http://vida.danguer.com/2008/09/01/mvc-en-zend-framework/" title="MVC en Zend Framework"></a><p><a title="MVC - Modelo-Vista-Controlador Wikipedia" href="http://es.wikipedia.org/wiki/Modelo_Vista_Controlador" target="_blank">MVC</a> es un acrónimo para Model-View-Controller (Modelo-Vista-Controlador); esta es un patrón de arquitectura de software.</p>
<p>Básicamente este patrón divide una aplicación (en nuestro caso una aplicación web) en tres partes:</p>
<ul>
<li><strong>Modelo</strong><br />
Es la parte que se entenderá con la base de datos, una manera elegante y clara de separar esto, es que para cada tabla generar una clase que será su Modelo, aunque en realidad podría ser que un Modelo controle varias tablas que tengan mucho en común, por ejemplo para las relaciones muchos-a-muchos.</li>
<li><strong>Controlador</strong><br />
Se encarga de procesar la entrada del usuario, en nuestro caso de recoger los datos de formularios, la URL, etc. Procesarlos (utilizando los otros componentes ya que esta parte debería ser la única que se comunica con los demás y las otras partes deben estar aisladas) y producir un resultado.</li>
<li><strong>Vista</strong><br />
Es la parte que maneja la parte que el usuario verá, el caso más común es tener una página en HTML, pero las posibilidades son que podemos tener incluso páginas en WAP (contenido móbil) o representaciones de texto. El controlador procesará todo lo necesario y enviará sus resultados a la vista (en el caso de Zend Framework mediante asignación de variables). La vista procesará todos los datos de una manera que sean claros para el usuario (aunque una vez más, esto podría ser incluso tener como salida por ejemplo XML para una API para comunicación entre librerías)</li>
</ul>
<p>En este tutorial veremos de manera introductoria como funciona el patrón de MVC con Zend Framework. Antes de ver el código, mostraremos como funciona básicamente Zend Framework con MVC mediante el siguiente esquema:</p>
<p><img src="http://vida.danguer.com/archivos/articulos/Zend_MVC/MVC_Proceso.png" alt="Proceso de MVC en Zend Framework" width="530" height="510" /></p>
<p>En el esquema el primer paso es cuando accedemos a una dirección, por ejemplo <code>http://www.danguer.com/ajax/resultado</code></p>
<p>La configuración de Zend Framework mediante Apache utilizando <a title="Mod-Rewrite Apache Ingles" href="http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html" target="_blank">Mod_Rewrite</a> hace que la mayoría de ligas (con algunas excepciones por ejemplo extensiones de hojas de estilo, javascript, etc) las procese el archivo index.php que contiene el código básico para inicializar el MVC que veremos más adelante.</p>
<p>Este archivo <code>index.php</code> tiene un código básico para inicializar toda la aplicación web, lo cual es ya de entrada interesante. Para la estructura de directorios será de la siguiente manera:</p>
<p><img src="http://vida.danguer.com/archivos/articulos/Zend_MVC/MVC_Estructura.png" alt="Estructura de Directorios de Zend Framework MVC" width="261" height="197" /></p>
<p>Tendremos la carpeta principal <code>app/</code> que será donde irá todo el código de PHP, dentro de esta carpeta tenemos varias carpetas pero las principales son:</p>
<ul>
<li><code>controllers</code>, donde estará el código de los controladores</li>
<li><code>models</code>, donde estará el código de los modelos (no lo utilizaremos)</li>
<li><code>layout</code>, las plantillas para el sitio (parte de las vistas)</li>
<li><code>views</code>, las vistas junto con &#8220;ayudantes&#8221; (<code>helpers</code>)</li>
</ul>
<p>La carpeta adicional <code>langs</code>, es una carpeta opcional y personal que he dejado del ejemplo de tutorial con <code>Zend_Form</code>, solo para ilustrar que se pueden crear carpetas adicionales sin problemas.</p>
<p>Como nota personal a mi me gusta dejar código que es necesario dentro de la carpeta <code>/app</code>, en el ejemplo se puede ver el archivo: <code>Danguer_Controller_Action.php</code> que después veremos a detalle. Esto es totalmente preferencia personal de como estructurar el archivo.</p>
<p>Después de la carpeta <code>/app</code>, hay una carpeta <code>styles/</code> que contiene archivos CSS, en realidad la carpeta no será visible para el usuario ya que <code>http://sitio/styles</code> intentará interpretarlo como código PHP mediante controladores como veremos más adelante.</p>
<p>Hay sugerencias de seguridad de como estructurar estas carpetas, pero en lo personal para mis desarrollos utilizo la estructura mostrada para no separar por completo el código y tenerlo todo en un solo lugar.</p>
<p>El archivo realmente importante es <code>index.php</code> y por supuesto <code>.htaccess</code>, el primero tiene el código de manejo para el MVC de Zend Framework y el segundo es un archivo para que Apache redireccione todas las peticiones al archivo <code>index.php</code></p>
<p><strong>Contenido del archivo <code>index.php</code> y <code>.htaccess</code></strong></p>
<p>El archivo .htaccess es muy simple, debido a que solamente habilita <code>Mod_Rewrite</code> y redirecciona todas las peticiones al archivo index.php:</p>
<pre name="code" class="php">RewriteEngine on

RewriteRule !\.(js|ico|gif|jpg|png|css|swf)$ index.php
</pre>
<p>La primera linea habilita <code>Mod_Rewrite</code>, la otra linea indica que salvo las ligas que contengan las extensiones <code>js</code>, <code>ico</code>, <code>gif</code>, <code>jpg</code>, <code>png</code>, <code>css</code> y <code>swf</code> deben procesarse con el archivo <code>index.php</code>, aqui se puede hacer que por ejemplo se habiliten algunos directorios para no ser procesador por el archivo <code>index.php</code> (por ejemplo un directorio de imagenes), pero esto debe ser tratado con cada caso en particular.</p>
<p>El archivo index.php contiene más lineas, pero son muy sencillas:</p>
<pre name="code" class="php">require_once 'Zend/Controller/Front.php';
require_once 'Zend/Layout.php';

require_once './app/Danguer_Controller_Action.php';

// Configurar controlador
$controller = Zend_Controller_Front::getInstance();
$controller-&gt;setControllerDirectory('./app/controllers');
$controller-&gt;throwExceptions(true); 

// asignar MVC
Zend_Layout::startMvc(array(
    'layoutPath' =&gt; './app/layouts',
    'layout' =&gt; 'principal'
	));

// ejecutar!
$controller-&gt;dispatch();
</pre>
<p>Las primeras lineas llaman las librerías necesarias que son el &#8220;despachador&#8221; de los controladores (<code>Zend/Controller/Front.php</code>) y la plantilla (<code>Zend/Layout.php</code>) la otra línea requiriendo un archivo en php (<code>./app/Danguer_Controller_Action.php</code>) será discutido más adelante, pero en esta parte podemos incluir todas los archivos/librerías que necesitemos, tanto de Zend como propios.</p>
<p>La siguiente línea de código genera el despachador, básicamente genera una instancia de este despachador (es única para toda la aplicación, por eso utilizamos de manera estática sin construirlo), asignamos el directorio de los controladores (<code>./app/controllers</code>) y por último permitimos que muestre excepciones por ser código en desarrollo (en producción se sugiere no utilizarlo para no dejar ver código importante a los usuarios).</p>
<p>La siguiente parte tiene como misión inicializar el sistema MVC de la parte de la plantilla. Anteriormente Zend Framework no manejaba plantillas en sus vistas, algo odioso porque se necesitaba crear un código propio (aunque había buenos ejemplos en la red). Actualmente con esa línea podemos definir la plantilla que utilizarán las vistas. Más adelante veremos como está hecha la plantilla.<br />
Con ese código hemos definido que el sistema debe buscar en el directorio <code>./app/layouts</code> las plantillas, y que la plantilla por defecto es &#8216;principal&#8217; que el archivo debe llamarse: <code>./app/layouts/principal.phtml</code></p>
<p>Con esto el sistema llamará a los controladores de la manera que veremos en la siguiente sección.</p>
<p><strong>Proceso del MVC</strong></p>
<p>Zend Framework una vez que tenga la liga (en este caso <code>/ajax/resultado</code>) procederá a &#8220;enrutarla&#8221;, es decir a convertir la liga en el controlador y acción deseada. Si no modificamos nada, por defecto el enrutamiento funciona de la siguiente manera:</p>
<pre name="code" class="php">http://sitio/controlador/accion
</pre>
<p>Así en nuestro ejemplo, el controlador es &#8220;<code>ajax</code>&#8221; y la acción es &#8220;<code>resultado</code>&#8220;. Por supuesto se pueden definir rutas alternativas, por ejemplo se puede decir que <code>http://sitio/blog/2008</code> sea el controlador &#8220;<code>blog</code>&#8220;, la acción &#8220;<code>archivos</code>&#8221; y pasarle a la acción un parámetro de nombre &#8220;<code>annio</code>&#8221; con el valor <code>2008</code>. Esto podría ser un alias de: <code>http://sitio/blog/archivos?annio=2008</code> que funciona bajo la configuración estándar</p>
<p>El ruteador puede ser tan personalizado que podemos pasar nuestro propio ruteador siempre y cuando se extienda de la interfaz: <code>Zend_Controller_Router_Interface</code>, o en su defecto que extienda la clase <code>Zend_Controller_Router_Abstract</code>, pero esto son temas avanzados que podemos discutir en otro tutorial =).</p>
<p>Una vez que el sistema sabe que controlador y acción es, procederá a llamar al controlador y a la acción. El controlador debe ser especificado de la siguiente forma:</p>
<pre name="code" class="php">&lt;?php
require_once 'Zend/Controller/Action.php';

class ControladorController extends Zend_Controller_Action {
    public function accionAction() {
         //codigo del controlador
    }
}
</pre>
<p>En donde el nombre de la clase debe ser el nombre del controlador iniciando con mayúscula y seguido por &#8216;<code>Controller</code>&#8216; (sin espacios) y cada nombre de función debe ser el nombre de la acción seguido por &#8216;<code>Action</code>&#8216; (sin espacios). El nombre del archivo debe ser igual que el nombre de la clase y se almacena dentro de la carpeta <code>/app/controllers</code>.</p>
<p>En el caso anterior para la liga <code>/ajax/resultado</code> nuestro archivo sería el siguiente:</p>
<pre name="code" class="php">&lt;?php
require_once 'Zend/Controller/Action.php';

class AjaxController extends Zend_Controller_Action {
    public function resultadoAction() {
         //codigo del controlador
    }
}
</pre>
<p>Cuando entremos a la liga mencionada, el sistema procesará todo el código en la función de la acción. Como vemos nuestra clase extiende de <code>Zend_Controller_Action</code>, esta clase contendrá básicamente:</p>
<ul>
<li>una petición (que contiene información de variables de entrada o del sistema)</li>
<li>una respuesta (que puede ser para redireccionar la página a otra por ejemplo)</li>
<li>la vista</li>
</ul>
<p>Por defecto el sistema crea una vista, crea las variables de la petición y la respuesta, llama a la función de la acción; y por último llama a un &#8220;ayudante&#8221; para que la vista sea generada y la salida se envia al navegador. Es por esto que dentro del controlador no llamaremos a la función <code>render</code> ya que la clase principal lo hace automáticamente.</p>
<p>Para obtener información de entrada, como un parámetro que se especificó mediante <code>/controlador/accion?variable=valor</code> utilizamos la variable de la petición de la siguiente manera:</p>
<pre name="code" class="php">$peticion = $this-&gt;getRequest();
$valor = $peticion-&gt;getParam('variable');
</pre>
<p>También existe una función <code>$peticion-&gt;getParams();</code> que regresa un arreglo asociativo con todas las variables y sus valores.</p>
<p>Para pasar una variable a la vista existe una variable <code>$this-&gt;view</code> dentro del controlador a la que podemos pasar valores de la siguiente forma:</p>
<pre name="code" class="php">$variable = 'Hola mundo';
$this-&gt;view-&gt;assign('variable', $variable);
//la vista ahora tendrá una variable que puede ser accesada como $this-&gt;variable
</pre>
<p>Más adelante veremos algunas opciones útiles para inicializar valores en la vista o cambiar el ciclo de renderizado de la vista.</p>
<p><strong>Vistas</strong></p>
<p>Las vistas deben ser guardadas en el directorio <code>apps/views/scripts/controlador/</code> con el nombre de archivo: <code>accion.phtml</code>, así por ejemplo para nuestro ejemplo de /ajax/resultado debemos crear el siguiente archivo: <code>apps/views/scripts/ajax/resultado.phtml</code></p>
<p>La vista contendrá archivo principalmente HTML, pero podemos procesar código PHP de forma normal entre <code>&lt;?php</code> y <code>?&gt;</code>, Zend también permite que las vistas utilicen cualquier otro sistema de plantillas que esté escrito en PHP, por ejemplo <a title="Proyecto de Smarty" href="http://www.smarty.net/" target="_blank">Smarty</a>.</p>
<p>Dentro llamamos a las variables que hemos asignado de la siguiente manera:</p>
<pre name="code" class="php">&lt;?=$this-&gt;variable?&gt;
</pre>
<p>Dentro de las vistas podemos alterar un poco la plantilla, para iniciar podemos cambiar el título de la siguiente manera:</p>
<pre name="code" class="php">&lt;?php
$this-&gt;headTitle('Ventana emergente');
?&gt;
</pre>
<p>Eso hará que el título de la página sea &#8220;Ventana Emergente&#8221;, pero también podemos agregar un archivo de hoja de estilo de la siguiente manera:</p>
<pre name="code" class="php">&lt;?php
$this-&gt;headLink()-&gt;appendStylesheet($this-&gt;baseUrl.'/styles/archivo.css', 'screen');
?&gt;
</pre>
<p>O incluir un archivo de javascript:</p>
<pre name="code" class="php">&lt;?php
$this-&gt;headScript()-&gt;appendFile($this-&gt;baseUrl.'/scripts/archivo.js');
?&gt;
</pre>
<p>El sistema de plantillas tiene algunas opciones extra que por brevedad no revisaremos, pero incluyen la posibilidad de incluir código en javascript/css que manejará de manera adecuada mediante una cadena.</p>
<p>La variable de <code>$this-&gt;baseUrl</code>, no es estándar de las vistas y es algo que yo he agregado y que veremos más adelante como se logra.</p>
<p><strong>Plantillas</strong></p>
<p>Las plantillas son muy simples, tienen el siguiente modelo:</p>
<pre name="code" class="php">&lt;?php
/* con esto establecemos un documento XHTML */
echo '&lt;?xml version="1.0" encoding="UTF-8" ?&gt;';
/* esto generará las cabeceras de XHTML,
   también podemos definir otras como HTML 4 */
echo $this-&gt;doctype()
?&gt;

&lt;html&gt;

	&lt;head&gt;
		&lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /&gt;
		&lt;!-- es bueno definir algunas etiquetas "globales" aunque pueden hacerse sobreescribiendo el Danguer_Action_Controller  --&gt;
		&lt;link type="text/css" href="&lt;?=$this-&gt;baseUrl?&gt;/styles/main.css" rel="stylesheet" /&gt;		

		&lt;?php
			/* Con esto nos aseguramos que el título siempre tenga un nombre al inicio */
			$this-&gt;headTitle('Ejemplo de MVC, danguer.com | ',Zend_View_Helper_Placeholder_Container_Abstract::PREPEND);

			echo $this-&gt;headTitle();
		    echo $this-&gt;headScript();
		    echo $this-&gt;headStyle();
	    ?&gt;
	&lt;/head&gt;

	&lt;body&gt;
		&lt;!--  solo contenido, esto puede ser usado para un popup --&gt;
		&lt;?php echo $this-&gt;layout()-&gt;content ?&gt;
	&lt;/body&gt;

&lt;/html&gt;
</pre>
<p>Como vemos definimos básicamente la plantilla del documento y definimos una parte que será donde irá el contenido con: <code>&lt;?php echo $this-&gt;layout()-&gt;content ?&gt;</code>, esta parte es reemplazada por la vista en cuestión.<br />
La otra parte dinámica es:</p>
<pre name="code" class="php">&lt;?php
			/* Con esto nos aseguramos que el título siempre tenga un nombre al inicio */
			$this-&gt;headTitle('Ejemplo de MVC, danguer.com | ',Zend_View_Helper_Placeholder_Container_Abstract::PREPEND);

			echo $this-&gt;headTitle();
		    echo $this-&gt;headScript();
		    echo $this-&gt;headStyle();
	    ?&gt;
</pre>
<p>Que se reemplazará como vimos anteriormente por el título de la página, los archivos de scripts y las hojas de estilo.</p>
<p>Una plantilla también puede tener zonas de contenido, donde desde la vista podemos llenarlas, por ejemplo podemos tener una zona que indique un mensaje y no tendremos que alterar la plantilla segmentándola en diferentes archivos como se suele hacer. Eso se verá en otro tutorial =)</p>
<p><strong>Controlador Base</strong></p>
<p>En lo particular me gusta crear un controlador base que contiene código de utilidad para mis aplicaciones, casi siempre utilizo uno. En el código de ejemplo tiene nombre: <code>app/Danguer_Controller_Action.php</code></p>
<p>Lo que hace este controlador base es lo siguiente:</p>
<ul>
<li>Asigna variables a la vista (por ejemplo <code>baseUrl</code> que es el directorio base de ligas relativas, muy útil para subdirectorios)</li>
<li>Permite deshabilitar el renderizado automático (ya que al finalizar la función intentará buscar el archivo de vista que puede no existir por ejemplo para resultados de <code>AJAX</code>)</li>
<li>Tiene funciones de utilidad, en el ejemplo tiene una función para enviar datos en formato <code>JSON </code>con el simple llamado de una función, pero puede incluir código que se compartan entre todos (o la mayoría) de controladores</li>
</ul>
<p>El código del controlador base es el siguiente:</p>
<pre name="code" class="php">&lt;?php
require_once 'Zend/Controller/Action.php';

class Danguer_Controller_Action extends Zend_Controller_Action {
	protected $autoRender = true;

    public function initView()
    {
    	parent::initView();

	    $this-&gt;view-&gt;assign('baseUrl', $this-&gt;getRequest()-&gt;getBaseUrl());
		$this-&gt;view-&gt;assign('fullUrl', $this-&gt;getFullURL());
    	return $this-&gt;view;
    }

    public function init() {
    	$this-&gt;initView();
    }

    public function disableAutoRender() {
    	$this-&gt;autoRender = false;
    	$args = $this-&gt;getInvokeArgs();   	

    	$args['noViewRenderer'] = true;
    	$this-&gt;_setInvokeArgs($args);

    	$this-&gt;_helper-&gt;resetHelpers();
    }

    protected function getFullURL() {
    	$protocol = 'http://';
    	$host = $_SERVER['HTTP_HOST'];
    	$port = $_SERVER['SERVER_PORT'];

    	if ($port != '80')
    		$port = ":{$port}";
    	else
   			$port = '';

    	return "{$protocol}{$host}{$port}".$this-&gt;getRequest()-&gt;getBaseUrl();
    }

	protected function writeJSON($data) {
		require_once 'Zend/Json.php';

		$this-&gt;disableAutoRender();
		header('Content-Type: text/javascript');

		print Zend_Json::encode($data);
	}
}
</pre>
<p>La función init (similar al constructor de clases) forza a iniciar la vista, en esa función (initView) se llama al padre para que genere el objeto de vista y le asignemos variables predefinidas. Aqui podemos incluir todas las variables que necesitemos.</p>
<p>Las otras dos funciones extras son:</p>
<ul>
<li><code>disableAutoRender</code><br />
Permite deshabilitar el auto-renderizado para que la aplicación no busque el archivo de la acción.</li>
<li><code>writeJSON</code><br />
Codifica una variable en formato JSON (apropiado para AJAX), también automáticamente deshabilita el auto-renderizado</li>
</ul>
<p>Estas funciones son ejemplo de lo que se puede lograr personalizando el sistema MVC.</p>
<p>Por último si se necesita modificar la plantilla, es muy sencillo; en el código del controlador simplemente necesitamos hacer los siguientes pasos:</p>
<pre name="code" class="php">$mvc = Zend_Layout::getMvcInstance();
$mvc-&gt;setLayout('simple'); //utilizar la plantilla app/layouts/simple.phtml
</pre>
<p>Esto es la base para entender el modelo MVC de Zend Framework, más adelante explicaré más a detalle cosas como los ayudantes, modelos y Ruteadores.</p>
<p>Código fuente: <a title="Ejemplo de Zend Framework MVC" href="http://vida.danguer.com/archivos/articulos/Zend_MVC/DanguerArticle_Zend_MVC.tar.gz" target="_self">DanguerArticle_Zend_MVC.tar.gz</a></p>
<p><a title="Sitio Demo Zend Framework MVC" href="http://demo.livesourcing.com/blog_vida/articulos/DanguerArticle_Zend_MVC" target="_blank">Ver sitio demo</a></p>
]]></content:encoded>
			<wfw:commentRss>http://vida.danguer.com/2008/09/01/mvc-en-zend-framework/feed/</wfw:commentRss>
		<slash:comments>27</slash:comments>
		</item>
		<item>
		<title>Zend Form: Decoradores</title>
		<link>http://vida.danguer.com/2008/08/31/zend-form-decoradores/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=zend-form-decoradores</link>
		<comments>http://vida.danguer.com/2008/08/31/zend-form-decoradores/#comments</comments>
		<pubDate>Mon, 01 Sep 2008 05:56:33 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Zend]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[Zend_Form]]></category>
		<category><![CDATA[Zend_Form_Decorator]]></category>

		<guid isPermaLink="false">http://vida.danguer.com/?p=49</guid>
		<description><![CDATA[<a href="http://vida.danguer.com/2008/08/31/zend-form-decoradores/" title="Zend Form: Decoradores"></a><p>Extendiendo un poco el tutorial de <a title="Formularios con Zend Form" href="http://vida.danguer.com/2008/05/formularios-con-zend-framework-zend_form/" target="_blank">Formularios Zend</a> ahora explicaré como funcionan los decoradores. Los decoradores son la manera de visualizar los diferentes elementos de la forma, básicamente se encargan de &#8216;renderizar&#8217; los elementos de una forma (es decir es la parte de la Vista).</p>
<p>En el tutorial anterior no definí ningún decorador, esto es porque el Zend Framework inicializa los decoradores con algunos por defecto. Veremos un poco del código interno del Zend Framework para entenderlo a detalle.</p>
<p>en <code>Zend/Form/Element.php</code> nos daremos cuenta que en el <code>__construct</code> (inicialización del elemento) hasta al final hay una llamada a la función <code>loadDefaultDecorators</code> que es la siguiente:</p>
<pre name="code" class="php">public function loadDefaultDecorators()
{
    if ($this-&#62;loadDefaultDecoratorsIsDisabled()) {
        return;
    }

    $decorators = $this-&#62;getDecorators();
    if (empty($decorators)) {
        $this-&#62;addDecorator('ViewHelper')
            -&#62;addDecorator('Errors')
            -&#62;addDecorator('HtmlTag', array('tag' =&#62; 'dd'))
            -&#62;addDecorator('Label', array('tag' =&#62; 'dt'));
    }
}</pre>
<p>Estos cuatro decoradores son la base de como los elementos son renderizados. El sistema procesa en orden lineal de como definimos los decoradores, si no modificamos entonces el orden es de procesar primero <code>ViewHelper</code>, luego <code>Errors</code>, <code>HtmlTag </code>y por último <code>Label</code>.</p>
<p>Cada decorador al momento de procesar en la función <code>render</code>, el sistema le pasa una cadena con el contenido actual y regresa una cadena de texto que procesó. Idealmente debe de utilizarse la cadena del contenido actual, pero con esto también podemos incluso procesar los elementos procesados y sobreescribir todo el resultado o hacer otras cosas interesantes (aunque podría ser no recomendable en un elemento que tenga como propósito ser parte de una librería).</p>
<p>Los elementos por defecto funciona de la siguiente manera:</p>
<ul>
<li><code>ViewHelper</code>: renderea en sí el elemento mediante un <code>helper</code>. Por ejemplo un elemento <code>Zend_Form_Element_Select</code> que tiene un helper <code>formSelect</code> utilizará este último helper para mostrar el elemento como <code>&#60;select&#62;...&#60;/select&#62;</code></li>
<li><code>Errors</code>: renderea las partes de los</li></ul><p>&#8230;</p>]]></description>
			<content:encoded><![CDATA[<a href="http://vida.danguer.com/2008/08/31/zend-form-decoradores/" title="Zend Form: Decoradores"></a><p>Extendiendo un poco el tutorial de <a title="Formularios con Zend Form" href="http://vida.danguer.com/2008/05/formularios-con-zend-framework-zend_form/" target="_blank">Formularios Zend</a> ahora explicaré como funcionan los decoradores. Los decoradores son la manera de visualizar los diferentes elementos de la forma, básicamente se encargan de &#8216;renderizar&#8217; los elementos de una forma (es decir es la parte de la Vista).</p>
<p>En el tutorial anterior no definí ningún decorador, esto es porque el Zend Framework inicializa los decoradores con algunos por defecto. Veremos un poco del código interno del Zend Framework para entenderlo a detalle.</p>
<p>en <code>Zend/Form/Element.php</code> nos daremos cuenta que en el <code>__construct</code> (inicialización del elemento) hasta al final hay una llamada a la función <code>loadDefaultDecorators</code> que es la siguiente:</p>
<pre name="code" class="php">public function loadDefaultDecorators()
{
    if ($this-&gt;loadDefaultDecoratorsIsDisabled()) {
        return;
    }

    $decorators = $this-&gt;getDecorators();
    if (empty($decorators)) {
        $this-&gt;addDecorator('ViewHelper')
            -&gt;addDecorator('Errors')
            -&gt;addDecorator('HtmlTag', array('tag' =&gt; 'dd'))
            -&gt;addDecorator('Label', array('tag' =&gt; 'dt'));
    }
}</pre>
<p>Estos cuatro decoradores son la base de como los elementos son renderizados. El sistema procesa en orden lineal de como definimos los decoradores, si no modificamos entonces el orden es de procesar primero <code>ViewHelper</code>, luego <code>Errors</code>, <code>HtmlTag </code>y por último <code>Label</code>.</p>
<p>Cada decorador al momento de procesar en la función <code>render</code>, el sistema le pasa una cadena con el contenido actual y regresa una cadena de texto que procesó. Idealmente debe de utilizarse la cadena del contenido actual, pero con esto también podemos incluso procesar los elementos procesados y sobreescribir todo el resultado o hacer otras cosas interesantes (aunque podría ser no recomendable en un elemento que tenga como propósito ser parte de una librería).</p>
<p>Los elementos por defecto funciona de la siguiente manera:</p>
<ul>
<li><code>ViewHelper</code>: renderea en sí el elemento mediante un <code>helper</code>. Por ejemplo un elemento <code>Zend_Form_Element_Select</code> que tiene un helper <code>formSelect</code> utilizará este último helper para mostrar el elemento como <code>&lt;select&gt;...&lt;/select&gt;</code></li>
<li><code>Errors</code>: renderea las partes de los errores, utiliza una plantilla de la siguiente forma:
<pre name="code" class="html">&lt;ul class="errores"[opciones html]&gt;
&lt;li&gt;[error1]&lt;/li&gt;
....
&lt;li&gt;[errorN]&lt;/li&gt;
&lt;/ul&gt;</pre>
</li>
<li><code>HtmlTag</code>: Le da un poco de formato al elemento ya que lo agrega en una plantilla de la siguiente forma:
<pre name="code" class="html">&lt;dd&gt;
...
&lt;/dd&gt;</pre>
</li>
<li><code>Label</code>: Asigna una etiqueta de la siguiente forma:
<pre name="code" class="html">&lt;dt&gt;&lt;label&gt;Etiqueta&lt;/label&gt;&lt;/dt&gt;</pre>
</li>
</ul>
<p>Los decoradores por defecto tienen opciones para ser puestos al inicio (<code>PREPEND</code>) o al final (<code>APPEND</code>) del contenido, por defecto <code>Errors</code> se pone al final, <code>HtmlTag </code>pone el contenido en medio de las etiquetas y <code>Label</code> se pone al inicio del contenido.</p>
<p>Por lo que con las opciones por defecto la plantilla de como se verá nuestro elemento es:</p>
<pre name="code" class="php">&lt;dt&gt;&lt;label&gt;[Etiqueta del elemento]&lt;/label</span>&gt;&lt;/dt&gt;
&lt;dd&gt;
    [Elemento]
    &lt;ul class="errors"&gt;
        &lt;li&gt;[Errores]&lt;/li&gt;
    &lt;/ul&gt;
&lt;/dd&gt;
</pre>
<p>Si queremos cambiar el orden, o forma de presentación tenemos que cambiar un poco el formato de salida; por ejemplo con el siguiente código (modificándolo de I<code>ndexController.php</code> del tutorial de <a href="http://vida.danguer.com/2008/05/formularios-con-zend-framework-zend_form/" target="_blank">Zend Form</a>):</p>
<pre name="code" class="php">$decoradores = array(
     'ViewHelper',
     'Errors',
     array('HtmlTag', array('tag' =&gt; 'div', 'class' =&gt; 'formElement')),
     array('Label', array('tag' =&gt; 'div'))
);

$nombre = $formulario-&gt;createElement('text', 'nombre_completo')
               -&gt;setLabel('Nombre Completo')
               -&gt;setDecorators($decoradores)
               -&gt;setRequired(true);</pre>
<p>Esto nos mostrará un resultado como el siguiente:</p>
<p><img src="http://vida.danguer.com/archivos/articulos/Zend_Form_Decorators/ejemplo1.png" alt="Ejemplo de Zend_Form_Decorator" width="232" height="208" /></p>
<p>Como hemos definido todos los decoradores que vamos a utilizar es fácil aplicarlo a los demás elementos (en el ejemplo anterior, sólo se aplicó al primer elemento.</p>
<p>Hay que hacer notar que sólo podemos utilizar una vez el decorador en un elemento, si agregamos otro <code>HtmlTag</code> por ejemplo, el último sobreescribirá al primero.</p>
<p>Si queremos construir algo más complejo existe un decorador que nos permite tener mucho mayor control: <code>ViewScript</code>, este decorador básicamente llamará a un archivo de la carpeta de vista (<code>views/scripts</code>) y le pasará tres parámetros:</p>
<ul>
<li><code>content</code>: El contenido actual producto del renderizado de los otros decoradores</li>
<li><code>element</code>: El <code>Zend_Form_Element</code> que estamos renderizados</li>
<li><code>decorator</code>: Una referencia al decorador <code>ViewScript</code></li>
</ul>
<p>Por defecto el resultado se agrega al final, si pasamos como opcion que la posición sea <code>false</code> entonces el contenido que resulte de renderizar este decorador será el único contenido.</p>
<p>Por ejemplo lo siguiente crea un &#8220;contenedor&#8221; al elemento:</p>
<pre name="code" class="php">$decoradores = array(
           'ViewHelper',
           'Errors',
           array('HtmlTag', array('tag' =&gt; 'div', 'class' =&gt; 'formElement')),
           array('Label', array('tag' =&gt; 'div')),
           array('ViewScript', array('viewScript' =&gt; 'decorador-contenedor.phtml', 'placement' =&gt; false)),
    );</pre>
<p>Y el decorador está especificado como (archivo nombreado como: <code>views/scripts/decorador-contenedor.phtml</code>:</p>
<pre name="code" class="html">&lt;div class="formElementContent"&gt;
	&lt;?=$this-&gt;content ?&gt;
&lt;/div&gt;</pre>
<p>El resultado es el siguiente (con un poco de CSS):<br />
<img src="http://vida.danguer.com/archivos/articulos/Zend_Form_Decorators/ejemplo2.png" alt="Ejemplo de Zend_Form_Decorator" /></p>
<p>Ahora bien, si queremos podemos prácticamente reconstruir todo los demás decoradores mediante un un decorador de <code>ViewHelper</code> y un decorador <code>ViewScript</code> de la siguiente manera:</p>
<pre name="code" class="php">$decoradores = array(
          'ViewHelper',
          array('ViewScript', array('viewScript' =&gt; 'decorador-avanzado.phtml', 'placement' =&gt; false)),
     );</pre>
<p>Y el decorador seria de la siguiente manera:</p>
<pre name="code" class="html">&lt;!-- Esta primera parte reemplazaria HtmlTag --&gt;
&lt;div class="formElementContent"&gt;
	&lt;!--  parte que remplaza el decorador Label --&gt;
	&lt;div&gt;
    &lt;?php
    	$attribs = $this-&gt;element-&gt;getAttribs();
    	$label = $this-&gt;element-&gt;getLabel();

    	//nuevo, verificamos si el elemento es requerido,
    	//entonces agregamos un elemento en html al final de la etiqueta
    	if ($this-&gt;element-&gt;isRequired()) {
    		$attribs['escape'] = false;
    		$label = $this-&gt;escape($label). ' &lt;span class="required"&gt;*&lt;/span&gt;';
    	}

    	echo $this-&gt;formLabel($this-&gt;element-&gt;getName(), $label, $attribs);
    ?&gt;
    &lt;/div&gt;

    &lt;!-- parte del elemento --&gt;
    &lt;?=$this-&gt;content ?&gt;

    &lt;!--
    	parte que reemplaza Errors
    	observen que estoy poniendo los errores
    	con simples saltos de linea en lugar de lista
     --&gt;
	&lt;?php if ($this-&gt;element-&gt;getMessages()) { ?&gt;
	&lt;div class="errors"&gt;
		&lt;?=implode('&lt;br /&gt;', $this-&gt;element-&gt;getMessages())?&gt;
	&lt;/div&gt;
	&lt;?php } ?&gt;

    &lt;!-- esta parte es opcional si agregaron una descripción --&gt;
    &lt;div class="hint"&gt;&lt;?= $this-&gt;element-&gt;getDescription() ?&gt;&lt;/div&gt;
&lt;/div&gt;</pre>
<p>El resultado con un poco de CSS es el siguiente:</p>
<p><img src="http://vida.danguer.com/archivos/articulos/Zend_Form_Decorators/ejemplo3.png" alt="Ejemplo de Zend_Form_Decorator" width="206" height="323" /></p>
<p>Como se puede observar el anterior ejemplo nos da completo control sobre como mostrar los elementos.</p>
<p>También en un caso más complejo y avanzado podemos incluso definir con algunos cambios sobre el formulario principal (Zend_Form) para definir un decorador que nos permita sobre la vista definir el orden de los elementos, mostrar un formulario totalmente estilizado que no sea regular o incluso no mostrar elementos o crear nuevos para cosas como AJAX/Javascript por ejemplo.</p>
<p>Pero de eso hablaría en otro pequeño tutorial =).</p>
<p>Código Fuente:</p>
<p><a title="Descargar Ejemplo Zend_Form_Decorator" href="http://vida.danguer.com/archivos/articulos/Zend_Form_Decorators/DanguerArticle_Zend_Form_Decorator.tar.gz" target="_self">DanguerArticle_Zend_Form_Decorator.tar.gz</a></p>
<p><a title="Ver Demo de Zend_Form_Decorator" href="http://demo.livesourcing.com/blog_vida/articulos/DanguerArticle_Zend_Form_Decorator/" target="_blank">Visitar Sitio Demo</a></p>
]]></content:encoded>
			<wfw:commentRss>http://vida.danguer.com/2008/08/31/zend-form-decoradores/feed/</wfw:commentRss>
		<slash:comments>24</slash:comments>
		</item>
		<item>
		<title>Formularios con Zend Framework (Zend_Form)</title>
		<link>http://vida.danguer.com/2008/05/06/formularios-con-zend-framework-zend_form/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=formularios-con-zend-framework-zend_form</link>
		<comments>http://vida.danguer.com/2008/05/06/formularios-con-zend-framework-zend_form/#comments</comments>
		<pubDate>Tue, 06 May 2008 22:03:46 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[Zend_Form]]></category>

		<guid isPermaLink="false">http://vida.danguer.com/?p=6</guid>
		<description><![CDATA[<a href="http://vida.danguer.com/2008/05/06/formularios-con-zend-framework-zend_form/" title="Formularios con Zend Framework (Zend_Form)"></a><p>Una de las características que se había solicitado en Zend Framework era la de poder utilizar formularios. En la versión 1.5 ya existe esta característica; aunque algunas partes de la documentación de Zend es muy vaga el poder de los formularios es excelente; como siempre tiene una muy buena arquitectura que va desde lo medianamente simple para utilizar los formularios de manera rápida hasta lo complejo que permite extender sus capacidades sin &#8216;hacks&#8217; en el código o rehaciendo partes de código vitales.</p>
<p>Un formulario (<code>Zend_Form</code>) es un contenedor de elementos (por ejemplo una entrada de texto, una casilla de verificación, etc), del lado del controlador debemos definir los elementos, una vez hecho esto entonces podemos visualizar (render) la forma del lado de la vista ya sea asignándole una vista o simplemente con <code>&#60;?=$formulario?&#62;</code> donde <code>$formulario</code> es por supuesto nuestro objeto de tipo Zend_Form</p>
<p>Los elementos que maneja <strong>Zend Framework</strong> son básicamente los objetos en HTML a los que estamos acostumbrados, pero no estamos limitados a ellos ya que podemos crear los elementos que necesitemos.<br />
Un elemento puede tener <strong>validadores</strong> (subclases de <code>Zend_Validate_Abstract)</code> que nos permiten validar la entrada, aunque ya existen muchos validadores muy útiles y de uso frecuente.<br />
El elemento puede ser asignado uno o varios &#8220;<strong>Decoradores</strong>&#8220;; un Decorador es un objeto que pasa información a un Helper de la vista, los decoradores que tiene <strong>Zend Framework</strong> integrado nos permiten fácilmente alterar la salida de un elemento y también añadir fácilmente un diseño.</p>
<p><strong>Esquema</strong></p>
<p>El siguiente es un esquema de cómo funciona <code>Zend_Form</code>, podemos ver que el controlador se encargará de crear el formato del formulario y la parte de vista se encargará de mostrar el formulario y de mostrar los errores que hayan surgido.</p>
<p><img src="http://vida.danguer.com/archivos/articulos/Zend_Form/Controlador-Vista.png" alt="Esquema de Zend_Form" width="530" height="668" /></p>
<p><strong>Crear un formulario</strong></p>
<p>Para crear un formulario debemos hacer lo siguiente:&#8230;</p>]]></description>
			<content:encoded><![CDATA[<a href="http://vida.danguer.com/2008/05/06/formularios-con-zend-framework-zend_form/" title="Formularios con Zend Framework (Zend_Form)"></a><p>Una de las características que se había solicitado en Zend Framework era la de poder utilizar formularios. En la versión 1.5 ya existe esta característica; aunque algunas partes de la documentación de Zend es muy vaga el poder de los formularios es excelente; como siempre tiene una muy buena arquitectura que va desde lo medianamente simple para utilizar los formularios de manera rápida hasta lo complejo que permite extender sus capacidades sin &#8216;hacks&#8217; en el código o rehaciendo partes de código vitales.</p>
<p>Un formulario (<code>Zend_Form</code>) es un contenedor de elementos (por ejemplo una entrada de texto, una casilla de verificación, etc), del lado del controlador debemos definir los elementos, una vez hecho esto entonces podemos visualizar (render) la forma del lado de la vista ya sea asignándole una vista o simplemente con <code>&lt;?=$formulario?&gt;</code> donde <code>$formulario</code> es por supuesto nuestro objeto de tipo Zend_Form</p>
<p>Los elementos que maneja <strong>Zend Framework</strong> son básicamente los objetos en HTML a los que estamos acostumbrados, pero no estamos limitados a ellos ya que podemos crear los elementos que necesitemos.<br />
Un elemento puede tener <strong>validadores</strong> (subclases de <code>Zend_Validate_Abstract)</code> que nos permiten validar la entrada, aunque ya existen muchos validadores muy útiles y de uso frecuente.<br />
El elemento puede ser asignado uno o varios &#8220;<strong>Decoradores</strong>&#8220;; un Decorador es un objeto que pasa información a un Helper de la vista, los decoradores que tiene <strong>Zend Framework</strong> integrado nos permiten fácilmente alterar la salida de un elemento y también añadir fácilmente un diseño.</p>
<p><strong>Esquema</strong></p>
<p>El siguiente es un esquema de cómo funciona <code>Zend_Form</code>, podemos ver que el controlador se encargará de crear el formato del formulario y la parte de vista se encargará de mostrar el formulario y de mostrar los errores que hayan surgido.</p>
<p><img src="http://vida.danguer.com/archivos/articulos/Zend_Form/Controlador-Vista.png" alt="Esquema de Zend_Form" width="530" height="668" /></p>
<p><strong>Crear un formulario</strong></p>
<p>Para crear un formulario debemos hacer lo siguiente:</p>
<ol>
<li>Crear un formulario (<code>Zend_Form</code>)</li>
<li>Crear elementos ya sea mediante<br />
<code>$elemento = $formulario-&gt;createElement('tipo_elemento', 'nombre_elemento');</code><br />
o mediante un objeto de tipo Zend_Form_Element:<br />
<code>$elemento = new Zend_Form_Element_Text('nombre_elemento');</code></li>
<li>Asignar propiedades al elemento:<br />
<code>setLabel('nombre_etiqueta'); //asigna el nombre de la etiqueta del elemento</code><br />
<code>setValue('valor'); //asigna el valor del elemento (sobreescribe la entrada del usuario)</code><br />
<code>setDecorators($arreglo_decoradores); //asigna los decoradores a usarse</code><br />
<code>setRequired(true/false); //indica si el valor no debe estar vacio</code><br />
<code>addValidator($validador); //indica el validador a utilizar</code></li>
<li>Agregar el elemento al formulario:<br />
<code>$formulario-&gt;addElement($elemento);</code><br />
los elementos se visualizarán en el orden en que han sido agregados, aunque esto puede cambiarse si se modifica el elemento mediante <code>$elemento-&gt;setOrder($numero);</code></li>
<li>Pasar el formulario a la vista para que sea renderizado:<br />
<code>$this-&gt;view-&gt;assign('formulario', $formulario);</code></li>
<li>Renderizarlo en la vista:<br />
<code>&lt;?=$this-&gt;formulario?&gt;</code></li>
</ol>
<p><strong>Validar un formulario</strong></p>
<p>Una vez que hemos renderizado el formulario y el usuario ha enviado datos, lo siguiente que debemos hacer es validar la entrada, para esto debemos de crear nuevamente el formulario y verificar si se han enviado datos (porque Zend Framework solo envia valores y no información sobre el formulario), si se han enviado datos entonces podemos utilizar la función <code>isValid($_POST);</code> que regresará un valor de verdadero en caso de que todos los validadores fueron satisfechos o falso en caso de que alguno no lo fuera.</p>
<p>La ventaja de Zend es que automáticamente agregará un mensaje de error al renderizar el elemento que tuvo un error; inicialmente el código de error estará en inglés, por lo que deberemos de traducir los mensajes (más adelante).</p>
<p><strong>Opciones de Validación</strong></p>
<p>Zend Framework tiene varias opciones para validar las entradas, todas ellas son subclases de <code>Zend_Validate_Abstract</code>, para agregar un validador debemos llamarlo de la siguiente manera:</p>
<p><code>$elemento-&gt;addValidator('nombre_validador', $romper_cadena_al_fallar, $arreglo_opciones);</code></p>
<p>Los validadores más importantes son (el nombre de validador es el que está entre paréntesis):</p>
<ul>
<li><code>Zend_Validate_Alnum</code> (<code>alnum</code>)<br />
Nos permite verificar que la entrada solo contenda caracteres alfanuméricos (letras y dígitos), opcionalmente se le puede pasar como opción un booleano para definir si se deben aceptar espacios en blanco (predeterminado en falso)</li>
<li><code>Zend_Validate_Alpha</code> (<code>alpha</code>)<br />
Nos permite verificar que la entrada sea sólo letras, al igual que el anterior permite una opción para aceptar espacios en blanco</li>
<li><code>Zend_Validate_Digits</code> (<code>digits</code>)<br />
Permite verificar que la entrada sea sólo números</li>
<li><code>Zend_Validate_StringLength</code> (<code>stringLength</code>)<br />
Nos permite definir que la entrada sólo contenga un número mínimo o máximo de valores; que deben ser especificado en las opciones por ejemplo:<br />
<code>$element-&gt;addValidator('stringLength', false, array(3, 20));</code><br />
Que especifica una cadena de al menos 3 caracteres y máximo 20 caracteres.</li>
<li><code>Zend_Validate_EmailAddress</code> (<code>emailAddress</code>)<br />
Es un validador muy poderoso que nos permite verificar que un correo sea válido (al menos en cuanto a formato y servidor válido incluso)</li>
<li><code>Zend_Validate_NotEmpty</code> (<code>notEmpty</code>)<br />
Este validador nos permite verificar que el usuario ha introducido un valor, lamentablemente no permite eliminar espacios en blanco con <code>trim </code>por ejemplo.</li>
</ul>
<p><strong>Traducción</strong></p>
<p>Los mensajes de error que mostrará Zend Framework de manera predeterminada serán en inglés; para poderlos mostrar en español debemos utilizar la parte de traducción de Zend (<code>Zend_Translate</code>).</p>
<p><code>Zend_Translate</code> permite muchas opciones pero aqui haremos una de las más básicas que es mediante un archivo PHP, esto nos permitirá usar las constantes de Zend, para esto simplemente hay que crear un archivo en PHP donde tendrá los mensajes en español, por ejemplo: <code>app/langs/es.php</code></p>
<p>En este archivo deberemos regresar un arreglo con la llave la cadena a traducir y el valor con la cadena traducida, por ejemplo:</p>
<pre name="code" class="php">&lt;?php
require_once 'Zend/Validate/NotEmpty.php';
require_once 'Zend/Validate/StringLength.php';
require_once 'Zend/Validate/EmailAddress.php';

return array(
Zend_Validate_NotEmpty::IS_EMPTY =&gt; 'El campo no puede estar vacío',
Zend_Validate_StringLength::TOO_LONG =&gt; 'El campo debe contener por lo menos %min% caracteres',
Zend_Validate_StringLength::TOO_SHORT =&gt; 'El campo debe contener un máximo de %max% caracteres',
Zend_Validate_EmailAddress::INVALID =&gt; 'La dirección de correo no es válida',
Zend_Validate_EmailAddress::QUOTED_STRING =&gt; "'%localPart%' no concuerda con el formato de comillas",
Zend_Validate_EmailAddress::DOT_ATOM =&gt; "'%localPart%' no concuerda con el formato de punto",
Zend_Validate_EmailAddress::INVALID_HOSTNAME =&gt; "'%hostname%' no es un nombre de dominio válido",
Zend_Validate_EmailAddress::INVALID_LOCAL_PART =&gt; "'%localPart%' no es una parte local válida",
Zend_Validate_EmailAddress::INVALID_MX_RECORD =&gt; "'%hostname%' no tiene un dominio de correo asignado",
);

?&gt;</pre>
<p>Debemos consultar la API para ver las cadenas que debemos traducir para cada validador. En el ejemplo sólo usaremos tres <code>notEmpty</code>, <code>stringLength</code> y <code>emailAddress</code></p>
<p>Entonces debemos de asignar estas traducciones a todos los componentes de Zend_Form de la siguiente manera:</p>
<pre name="code"  class="php">$traduccion = new Zend_Translate('array', 'app/langs/es.php', 'es');
Zend_Form::setDefaultTranslator($traduccion);</pre>
<p><strong>Obtención de Valores</strong></p>
<p>Los valores del formulario estarán en <code>$_POST['nombre_elemento']</code> o <code>$_GET['nombre_elemento']</code> según sea el caso, pero podemos pedirle al formulario que nos regrese solamente los valores que le corresponden de la entrada (si es que pasamos más datos), por lo que debemos hacer:</p>
<p><code>$valores = $formulario-&gt;getValues();</code></p>
<p><strong>Ejemplo</strong></p>
<p>Para el ejemplo tendremos dos archivos, <code>IndexController.php</code> (Controlador) e <code>index.phtml </code>(vista), simplemente mostraremos un formulario y mostraremos los valores.</p>
<p>El código del ejemplo puede ser obtenido en esta liga:<br />
<a title="Ejemplo de Zend_Form - Descargar" href="http://vida.danguer.com/archivos/articulos/Zend_Form/DanguerArticle_Zend_Form.tar.gz" target="_self">http://vida.danguer.com/archivos/articulos/Zend_Form/DanguerArticle_Zend_Form.tar.gz</a></p>
<p>Mientras que el ejemplo puede visualizarse en la siguiente liga:<br />
<a title="Ejemplo de Zend_Form" href="http://dev.fangit.com/DanguerArticle_Zend_Form/" target="_blank">http://dev.fangit.com/DanguerArticle_Zend_Form/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://vida.danguer.com/2008/05/06/formularios-con-zend-framework-zend_form/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
	</channel>
</rss>

