<?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>Backtheweb &#187; Zend Framework</title>
	<atom:link href="http://www.backtheweb.com/tag/zend-framework/feed" rel="self" type="application/rss+xml" />
	<link>http://www.backtheweb.com</link>
	<description>Notas y recursos de un desarrollador web</description>
	<lastBuildDate>Fri, 06 Jan 2012 01:58:36 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Zend Service Amazon response status code 400</title>
		<link>http://www.backtheweb.com/zend-framework/zend-service-amazon-response-status-code-400.html</link>
		<comments>http://www.backtheweb.com/zend-framework/zend-service-amazon-response-status-code-400.html#comments</comments>
		<pubDate>Sun, 11 Dec 2011 23:16:38 +0000</pubDate>
		<dc:creator>Jordi Touza Bonnin</dc:creator>
				<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[Amazon]]></category>

		<guid isPermaLink="false">http://www.backtheweb.com/?p=437</guid>
		<description><![CDATA[Hoy, al hacer pruebas con Zend_Service_Amazon me he encontrado con esto&#8230; Message: An error occurred sending request. Status code: 400 Y por mucho que googleara no encontraba el error&#8230; entre debugando y metiendo mano al código, miro la hora y veo que son las 2:00 de la madrugada&#8230; mmm&#8230; ups no, no puden ser las [...]]]></description>
			<content:encoded><![CDATA[<p>Hoy, al hacer pruebas con <strong>Zend_Service_Amazon</strong> me he encontrado con esto&#8230;<br />
<code>Message: An error occurred sending request. Status code: 400</code><br />
Y por mucho que googleara no encontraba el error&#8230; entre debugando y metiendo mano al código, miro la hora y veo que son las 2:00 de la madrugada&#8230; mmm&#8230; ups no, no puden ser las 2:00&#8230; el reloj de la maquina virtual está mal. Voilà! </p>
<p>Solución: ¡ajustar la hora del servidor!</p>
<p>Por otra parte&#8230; y no tiene nada que ver, parece ser que lleva unos días caido pear.phpunit.de, por lo que instalar phpunit desde pear es imposible</p>
]]></content:encoded>
			<wfw:commentRss>http://www.backtheweb.com/zend-framework/zend-service-amazon-response-status-code-400.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Zend Form Decorator, parte II</title>
		<link>http://www.backtheweb.com/zend-framework/zend-form-decorator-parte-ii.html</link>
		<comments>http://www.backtheweb.com/zend-framework/zend-form-decorator-parte-ii.html#comments</comments>
		<pubDate>Mon, 18 Oct 2010 22:34:10 +0000</pubDate>
		<dc:creator>Jordi Touza Bonnin</dc:creator>
				<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://www.backtheweb.com/?p=402</guid>
		<description><![CDATA[Anteriormente en la primera parte de Zend Form Decorators vimos como cambiar los Decorators directamente sobre el Zend Form. Ahora vamos a ver como aplicar nuestros propios decorators en todos los formularios de una estacada. class ZendY_Form extends Zend_Form{ protected static $_standardElementDecorator = array( array('ViewHelper'), array('Label', array('separator' =&#62; ' ', )), array('Description', array('tag' =&#62; 'span', [...]]]></description>
			<content:encoded><![CDATA[<p>Anteriormente en la <a href="http://www.backtheweb.com/php/zend-form-decorator-parte-i.html">primera parte de Zend Form Decorators</a> vimos como cambiar los <strong>Decorators</strong> directamente sobre el <code class="class">Zend Form</code>.<br />
Ahora vamos a ver como aplicar nuestros propios decorators en todos los formularios de una estacada.</p>
<p><span id="more-402"></span></p>
<p><code> </code></p>
<pre>class ZendY_Form extends Zend_Form{

    protected static $_standardElementDecorator   = array(
        array('ViewHelper'),
        array('Label',         array('separator' =&gt; ' ', )),
        array('Description',    array('tag' =&gt; 'span', 'class' =&gt; 'element-description-append', 'placement' =&gt; 'append' )),
        array('Errors'),
        array('HtmlTag',     array('tag' =&gt; 'div')),
    );  

    protected static $_standardElementDecoratorAppendDescription = array(
        array('Description',    array('tag' =&gt; 'span', 'class' =&gt; 'element-description-prepend', 'placement' =&gt; 'prepend' )),
        array('ViewHelper'),
        array('Label',         array('separator' =&gt; ' ', )),
        array('Errors'),
        array('HtmlTag',     array('tag' =&gt; 'div')),
    );

    protected static $_standardElementDecoratorClearRight   = array(
        array('ViewHelper'),
        array('Label',         array('separator' =&gt; ' ', )),
        array('Description',    array('tag' =&gt; 'span', 'class' =&gt; 'element-description-append', 'placement' =&gt; 'append' )),
        array('Errors'),
        array('HtmlTag',     array('tag' =&gt; 'div', 'class' =&gt; 'clearRight')),
    ); 

    protected static $_standardElementDecoratorClearLeft   = array(
        array('ViewHelper'),
        array('Label',         array('separator' =&gt; ' ', )),
        array('Description',    array('tag' =&gt; 'span', 'class' =&gt; 'element-description-append', 'placement' =&gt; 'append' )),
        array('Errors'),
        array('HtmlTag',     array('tag' =&gt; 'div', 'class' =&gt; 'clearLeft')),
    ); 

    /**
     *
     * Remeber to set 'separator' =&gt; '' into the element
     * @var array
     */
    protected static $_multiCheckboxElementDecorator = array(

        array('ViewHelper'),
        array('Label',         array('separator' =&gt; ' ', 'tag' =&gt; 'span')),
        array('Description',    array('tag' =&gt; 'span', 'class' =&gt; 'element-description-append', 'placement' =&gt; 'append' )),
        array('Errors'),
        array('HtmlTag',     array('tag' =&gt; 'div', 'class' =&gt; 'multiCheckbox')),

    );

    protected static $_hiddenElementDecorator = array(
        array('ViewHelper')
    );

    protected static $_submitElementDecorator = array(
        array('ViewHelper'),
        array('HtmlTag',         array('tag' =&gt; 'p', 'class' =&gt; 'element-submit')),
    );

    public function __construct($options = null)
    {
        parent::__construct($options);

    //$this-&gt;addElementPrefixPath('ZendY_Form_Decorator','ZendY/Form/Decorator','decorator');
    }

    /**
     * Load the default decorators
     *
     * @return void
     */
    public function loadDefaultDecorators(){

        if (!$this-&gt;loadDefaultDecoratorsIsDisabled()) {

            //$this-&gt;removeDecorator('DtDdWrapper');
            //$this-&gt;removeDecorator('DlWrapper'); 

            $this-&gt;clearDecorators()
                -&gt;setAttrib('accept-charset', 'UTF-8')
                -&gt;addDecorator('FormElements')
                -&gt;addDecorator('HtmlTag', array('tag' =&gt; '
<div>', 'class' =&gt; 'zendy_formContent'))
                -&gt;addDecorator('Form')
                -&gt;setAttrib('class', 'zendy_form')
            ;
        } 

        foreach ($this-&gt;getDisplayGroups() as $group){

            if($group-&gt;loadDefaultDecoratorsIsDisabled()) continue;

            $group-&gt;clearDecorators();

            $group-&gt;addDecorators(
                array(
                    array('FormElements'),
                    array('Description', array('tag' =&gt; 'p', 'class' =&gt; 'group-description', 'placement' =&gt; 'prepend' )),
                    new Zend_Form_Decorator_Fieldset(),
                )
            );
        }

        foreach ($this-&gt;getElements() as $element) {

            if($element-&gt;loadDefaultDecoratorsIsDisabled()) continue;

            switch ($element-&gt;getType()){

                case 'Zend_Form_Element_Hidden':      $element-&gt;setDecorators(self::$_hiddenElementDecorator);        break;
                case 'Zend_Form_Element_Submit':      $element-&gt;setDecorators(self::$_submitElementDecorator);        break;
                case 'Zend_Form_Element_Radio':
                case 'Zend_Form_Element_MultiCheckbox': $element-&gt;setDecorators(self::$_multiCheckboxElementDecorator); break;
                case 'Zend_Form_Element_Select':
                case 'Zend_Form_Element_Text':
                default:                                $element-&gt;setDecorators(self::$_standardElementDecorator);
            }
        }

        return $this;
    }
}</div>
</pre>
<p>Se trata de crear una clase que extienda <code>Zend Form</code> en la que definimos nuestros <strong>Decorators</strong>, tambien se podria crear una clase para cada decorator, pero eso lo dejo para otra entrada.</p>
<p>Una vez definidos los <strong>Decorators</strong> para <em>Elementos</em> y <em>DisplayGroups</em> los llamamos en el metodo <code>loadDefaultDecorators</code>.</p>
<p>Ahora cuando creamos un formulario extenderemos de <code>ZendY_Form</code> y se aplicaran los <strong>Decorators</strong> que hemos definido.</p>
<p>A de más si queremos que algun elemento tenga un <strong>decorator</strong> diferente podemos ahcer lo siguiente:</p>
<p><code> </code></p>
<pre>$this-&gt;addElement('text', 'validAtTo', array(
            'label'     =&gt; 'To',
            'required'  =&gt; false,
            'class'     =&gt; 'date',
            'value'     =&gt; '',
            'disableLoadDefaultDecorators' =&gt; true,
            'decorators' =&gt; parent::$_standardElementDecoratorClearLeft
        ));</pre>
<p>De esta forma, desactivamos los <strong>Decorators</strong> por defecto y cargamos otros que previamente hemos definido en nuestro clase <code>ZendY_Form</code></p>
<p>Espero que os sea útil</p>
]]></content:encoded>
			<wfw:commentRss>http://www.backtheweb.com/zend-framework/zend-form-decorator-parte-ii.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Zend Navigation especifico por módulo</title>
		<link>http://www.backtheweb.com/zend-framework/zend-navigation-especifico-por-modulo.html</link>
		<comments>http://www.backtheweb.com/zend-framework/zend-navigation-especifico-por-modulo.html#comments</comments>
		<pubDate>Sun, 08 Aug 2010 00:28:27 +0000</pubDate>
		<dc:creator>Jordi Touza Bonnin</dc:creator>
				<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[Zend Navigation]]></category>

		<guid isPermaLink="false">http://www.backtheweb.com/?p=379</guid>
		<description><![CDATA[Retomando el tema de un Layout especifico por cada módulo en Zend framework toca ahora ver como hacer una navegación especifica para cada módulo. Zend Framework nos permite configurar la nevegación de tres formas distintas: Directamente en PHP En un fichero XML En un fichero .INI Al principio usaba un fichero XML para conigurar Zend_Navigarion [...]]]></description>
			<content:encoded><![CDATA[<p>Retomando el tema de un <a title="Layout especifico para cada módulo en Zend Framework" href="http://www.backtheweb.com/php/zend-framework-como-hacer-un-layout-para-cada-modulo.html">Layout especifico por cada módulo en Zend framework</a> toca ahora ver como hacer una navegación especifica para cada módulo.</p>
<p><strong>Zend Framework</strong> nos permite configurar la nevegación de tres formas distintas:</p>
<ul>
<li>Directamente en <strong>PHP</strong></li>
<li>En un fichero <strong>XML</strong></li>
<li>En un fichero <strong>.INI</strong></li>
</ul>
<p>Al principio usaba un fichero <strong>XML</strong> para conigurar <strong>Zend_Navigarion</strong> y en el <code>boostrap</code> una función que carga dicho fichero:<br />
<span id="more-379"></span></p>
<pre><code>
protected function _initNavigation(){	

	$this-&gt;bootstrap('layout');
	$layout 	= $this-&gt;getResource('layout');
	$view 	= $layout-&gt;getView();

	$config 	= new Zend_Config_Xml(APPLICATION_PATH . '/configs/navigation.xml', 'navigation');
	$navigation = new Zend_Navigation($config);

	Zend_Registry::set('Zend_Navigation', $navigation);
}
</code></pre>
<p>Dado que estoy usando<strong> Zend_Application</strong> para manejar el proyecto tan solo necesito cargar el fichero <strong>XML</strong>, crear una instanca de <strong>Zend_Navigation</strong> y luego registrarla con <strong>Zend_Registry</strong> para que automaticamente la asuma la aplicación y poder usarla desde la vista.</p>
<p>Si tu navegación no es muy larga, tal vez te resulte más práctico usar el ficchero <code>application.ini</code>, pues no tendrás que hacer nada en el <code>bootstrap</code>.</p>
<p>Pero el problema surge, como en todos los otros recursos (Zend_Application_Resource_*), cuando quiero que cada módulo disponga de su propia navegación. Al intentarlo, <strong>Zend_Registry</strong> siempre se quedará con la última instancia, por lo que todos los módulos tendrán siempre la misma navegación. Esto es por  que <strong>Zend_Application</strong> carga todos los ficheros <code>bootstrap</code> de  cada módulo.</p>
<p>Esto es así y seguirá siendo así por que el <code>bootstrap</code> no es el lugar para configurar estos recursos (no lo digo yo). Por esta razón hemos de inicializar todas estas acciones mediante plugins.</p>
<p>Para empezar crearemos la estructura de la naevación en el fichero <code>application.ini</code>:</p>
<pre><code>;Navegación principal
resources.navigation.storage.registry           = true
resources.navigation.pages.page001.label        = "Home"
resources.navigation.pages.page001.uri          = "/"
resources.navigation.pages.page001.controller   = "index"<code>

;Navegación Admin
admin.resources.navigation.pages.clients.label 			= "Clients"
admin.resources.navigation.pages.clients.controller		= "clients"
admin.resources.navigation.pages.clients.module			= "admin"

admin.resources.navigation.pages.clients.pages.pageA.label		= "List"
admin.resources.navigation.pages.clients.pages.pageA.controller  = "clients"
admin.resources.navigation.pages.clients.pages.pageA.action		= "index"
admin.resources.navigation.pages.clients.pages.pageA.module		= "admin"

</code></code></pre>
<p>Es muy importante la primera linea <code>resources.navigation.storage.registry</code> en cada bloque de navegación, sin esto no funcionará. Lo que hace es que nos registra la navegación automáticamente.</p>
<p>Entonces, para inicializar una navegación especifica para cada módulo crearemos un plugin practicamente igual al que comente en el otro post <a title="Layout especifico para cada módulo en Zend Framework" href="http://www.backtheweb.com/php/zend-framework-como-hacer-un-layout-para-cada-modulo.html">Como hacer un Layout para cada módulo</a>. En mi caso tan solo he de añadir unas lineas:</p>
<pre><code>if(isset($config[$module]['resources']['navigation']['pages'])){
	$navigation = new Zend_Navigation($config[$module]['resources']['navigation']['pages']);
	Zend_Layout::getMvcInstance()-&gt;getView()-&gt;navigation($navigation);
}
</code></pre>
<p>Si prefieres o ya has creado un fichero XML (mucho más manejable) puedes hacer lo siguiente en lugar de lo anterior:</p>
<pre><code>
if(isset($config[$module]['resources']['navigation']['storage']['registry'])){
	$configIni = new Zend_Config_Xml(APPLICATION_PATH . '/configs/navigation.' . $module . '.xml', 'navigation');
	$navigation = new Zend_Navigation($configIni);
	Zend_Layout::getMvcInstance()->getView()->navigation($navigation);
}
</code></pre>
<p>De esta forma mi plugin queda de la siguiente manera:</p>
<pre><code>
class ZendY_Controller_Plugin_Layout extends Zend_Controller_plugin_Abstract {

	public function preDispatch(Zend_Controller_Request_Abstract $request) {

		$config = Zend_Controller_Front::getInstance ()-&gt;getParam ( 'bootstrap' )-&gt;getOptions ();
		$module = $request-&gt;getModuleName();

		if($module === "default") return;

		// Helpers Path
		Zend_Controller_Action_HelperBroker::addPath ( APPLICATION_PATH . '/modules/' . $module . '/helpers' );

		//basePath
		if (isset ( $config [$module] ['resources'] ['view'] ['basePath'] )) {
			$viewBasePath = $config [$module] ['resources'] ['view'] ['basePath'];
			Zend_Layout::getMvcInstance ()-&gt;setViewScriptPath ( $viewBasePath );
		}

		//Layout path
		if (isset ( $config [$module] ['resources'] ['layout'] ['layoutPath'] )) {
			$layoutPath = $config [$module] ['resources'] ['layout'] ['layoutPath'];
			Zend_Layout::getMvcInstance ()-&gt;setLayoutPath ( $layoutPath );
		}

		//LayoutScripts path
		if (isset ( $config [$module] ['resources'] ['layout'] ['layout'] )) {
			$layoutScript = $config [$module] ['resources'] ['layout'] ['layout'];
			Zend_Layout::getMvcInstance ()-&gt;setLayout ( $layoutScript );
		}

		//Navigation
		f(isset($config[$module]['resources']['navigation']['storage']['registry'])){
			$configIni = new Zend_Config_Xml(APPLICATION_PATH . '/configs/navigation.' . $module . '.xml', 'navigation');
			$navigation = new Zend_Navigation($configIni);
			Zend_Layout::getMvcInstance()->getView()->navigation($navigation);
		}
	}
}
</code></pre>
<p>Y recordar que para que el plugin funcione debeis regitrar su llamada en el <code>boostrap</code></p>
<pre><code>
protected function _initPlugins(){

	$bootstrap = $this-&gt;getApplication();
        $bootstrap-&gt;bootstrap('frontcontroller');
        $front = $bootstrap-&gt;getResource('frontcontroller');
	$front-&gt;registerPlugin(new ZendY_Controller_Plugin_Layout());
}
</code></pre>
<p>o en el mismo <code>application.ini</code></p>
<pre><code>
resources.frontController.plugins.layout 			= ZendY_Controller_Plugin_Layout
</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.backtheweb.com/zend-framework/zend-navigation-especifico-por-modulo.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Zend Form Decorator, parte I</title>
		<link>http://www.backtheweb.com/zend-framework/zend-form-decorator-parte-i.html</link>
		<comments>http://www.backtheweb.com/zend-framework/zend-form-decorator-parte-i.html#comments</comments>
		<pubDate>Fri, 20 Nov 2009 23:05:08 +0000</pubDate>
		<dc:creator>Jordi Touza Bonnin</dc:creator>
				<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://www.backtheweb.com/?p=347</guid>
		<description><![CDATA[Los formularios de Zend Framework es una de las cosas que más me gustan del framework porque te permite validar, procesar y modificar los formularios de una forma muy rápida y limpia. No obstante, de entrada queda todo muy limitado por la forma de presentar los datos con una lista de definición (dl). Aveces soy [...]]]></description>
			<content:encoded><![CDATA[<p>Los <strong>formularios</strong> de <strong>Zend Framework</strong> es una de las cosas que más me gustan del <em>framework</em> porque te permite validar, procesar y modificar los formularios de una forma muy rápida y limpia. No obstante, de entrada queda todo muy limitado por la forma de presentar los datos con una <em>lista de definición (dl)</em>. Aveces soy muy purista, y usar <code>dl</code>, <code>dt</code> y <code>dd</code> para maquetar un formulario no lo encuentro nada semántico (y tampoco con li).</p>
<p>La primera necesidad que me surge es cambiar el <code>dl</code> por un <code>div</code> y los <code>dt</code>&#8216;s y <code>dd</code>&#8216;s por <code>p</code>&#8216;s del <strong>formulario</strong>:</p>
<pre><code>$form-&gt;clearDecorators()
	-&gt;addDecorator('FormElements')
	-&gt;addDecorator('HtmlTag', 	array('tag' =&gt; '</code>', 'class' =&gt; 'zend_form'))
	-&gt;addDecorator('Form')
	-&gt;setElementDecorators(array(
		array('ViewHelper'),
		array('Errors'),
		array('Description', 	array('tag' =&gt; 'span', 'class' =&gt; 'element-description')),
		array('Label', 			array('separator' =&gt; ' ')),
		array('HtmlTag', 		array('tag' =&gt; 'p', 'class' =&gt; 'element-group')
	),
));</pre>
<p><span id="more-347"></span>De esta forma todos los elementos del <strong>formulario</strong> estarán construidos con una <code>p</code> y con la clase <code>element-group</code>, las ayudas descriptivas estaran dentro de la misma <code>p</code> pero dentro de un <code>span</code> y con la clase <code>element-group-description</code></p>
<p>El segundo aspecto es hacer que el <code>submit</code> no tenga <code>label</code>, para eso basta con no ponerlo, pero al hacerlo con listas de definición nos crea un <code>dt</code> vacío. pero además quiero que disponga de un <em>link</em> de &#8220;volver&#8221; o &#8220;cancelar&#8221;:</p>
<pre><code>$form-&gt;addElement('submit', 'submit', array(
	'ignore'   		=&gt; true,
	'description'	=&gt; '&lt;a href=\"#\"&gt;Cancel&lt;/a&gt;',
	'decorators' 	=&gt; array(
		array('ViewHelper'),
		array('Description', 	array('escape' =&gt; false, 'tag' =&gt; 'span', 'class'=&gt;'element-canel-link')),
		array('HtmlTag', 		array('tag' =&gt; 'p', 'class'=&gt;'submit-group'))
	)
));</code></pre>
<p>Aquí lo importante son los valores que pasamos a la array <code>Description</code> y lo mismo lo podemos hacer para un <code>input</code>.</p>
<pre><code>$form-&gt;addElement('password', 'credential', array(
	'label'      	=&gt; 'Password',
	'required'   	=&gt; true,
	'filters'    =&gt; array('StringTrim', 'StripTags'),
	'description'	=&gt; '&lt;a href=\"#\"&gt;Remember password&lt;/a&gt;',
	'decorators' 	=&gt; array(
		array('ViewHelper'),
		array('Description', 	array('escape' =&gt; false, 'tag' =&gt; 'span', 'class'=&gt;'element-description')),
		array('Label', 			array('separator'=&gt;' ')),
		array('Errors'),
		array('HtmlTag', 		array('tag' =&gt; 'p', 'class'=&gt;'element-group'))
	)
));</code></pre>
<p>Otro gran problema que se presenta con <strong>Zend Form</strong> es que al imprimir un <em>checkbox</em> lo pone después del <code>label</code> y eso es poco usable.</p>
<pre><code>$form-&gt;addElement('checkbox', 'rememberme', array(
	'label'     =&gt; 'Remember me',
	'value'		=&gt; '1',
	'checked' 	=&gt; false,
	'decorators' 	=&gt; array(
		array('ViewHelper'),
		array('Label', 			array('placement' =&gt; 'APPEND')),
		array('Errors'),
		array('HtmlTag', 		array('tag' =&gt; 'p', 'class'=&gt;'element-group'))
	)
));</code></pre>
<p>(Creo que aquí hay un bug, además del <code>checbox</code> me ha añadido un <code>input hidden</code>, pero no debería darnos muchos problemas, espero))</p>
<p>De esta forma my clase formulario queda así:</p>
<pre><code>class Default_Form_Login extends Zend_Form
{
    /**
     * init()
     *
     * @see    http://framework.zend.com/manual/en/zend.form.html
     * @return void
     */
    public function init()
    {
        // Set the method for the display form to POST
        $this-&gt;setMethod('post');
        $this-&gt;setAction('/auth/login/');
        $this-&gt;setAttrib('id', 'loginForm');

        $this-&gt;clearDecorators()
        	-&gt;addDecorator('FormElements')
         	-&gt;addDecorator('HtmlTag', array('tag' =&gt; '
</code>
<div>', 'class' =&gt; 'zend_form'))
         	-&gt;addDecorator('Form')
        	-&gt;setElementDecorators(array(
	            array('ViewHelper'),
	            array('Errors'),
	            array('Description',	array('tag' =&gt; 'span', 'class' =&gt; 'element-description')),
	            array('Label', 			array('separator' =&gt; ' ')),
	            array('HtmlTag', 		array('tag' =&gt; 'p', 'class' =&gt; 'element-group')
			),
        ));

        $this-&gt;addElement('text', 'identity', array(
            'label'      	=&gt; 'Email',
        	'value'			=&gt; '',
            'required'   	=&gt; true,
            'filters'    	=&gt; array('StringTrim', 'StripTags', 'StringToLower'),
        	'validators' 	=&gt; array('EmailAddress'),
        ));

        $this-&gt;addElement('password', 'credential', array(
            'label'      	=&gt; 'Password',
            'required'   	=&gt; true,
        	'filters'    =&gt; array('StringTrim', 'StripTags'),
        	'description'	=&gt; '&lt;a href=\"#\"&gt;Remember password&lt;/a&gt;',
			'decorators' 	=&gt; array(
				array('ViewHelper'),
	            array('Description', 	array('escape' =&gt; false, 'tag' =&gt; 'span', 'class'=&gt;'element-description')),
	            array('Label', 			array('separator'=&gt;' ')),
	            array('Errors'),
				array('HtmlTag', 		array('tag' =&gt; 'p', 'class'=&gt;'element-group'))
			)
        ));

        $this-&gt;addElement('checkbox', 'rememberme', array(
            'label'     =&gt; 'Remember me',
            'value'		=&gt; '1',
        	'checked' 	=&gt; false,
        	'decorators' 	=&gt; array(
				array('ViewHelper'),
	            array('Label', 			array('placement' =&gt; 'APPEND')),
	            array('Errors'),
				array('HtmlTag', 		array('tag' =&gt; 'p', 'class'=&gt;'element-group'))
			)
        ));

        // Add the submit button
       	$this-&gt;addElement('submit', 'submit', array(
            'ignore'   		=&gt; true,
       		'description'	=&gt; '&lt;a href=\"#\"&gt;Cancel&lt;/a&gt;',
       		//set decorator
			'decorators' 	=&gt; array(
				array('ViewHelper'),
				array('Description', 	array('escape' =&gt; false, 'tag' =&gt; 'span', 'class'=&gt;'element-canel-link')),
				array('HtmlTag', 		array('tag' =&gt; 'p', 'class'=&gt;'submit-group'))
			)
        ));

        // And finally add some CSRF protection
        $this-&gt;addElement('hash', 'csrf', array(
        	'ignore' =&gt; true,
       		//set decorator
        	'decorators' =&gt;
			array(
				array('ViewHelper'),
				array('HtmlTag', 		array('tag' =&gt; 'p', 'class'=&gt;'element-group-hidden'))
			)
        ));
    }
}</div>
</pre>
<p>Lo ideal sería crear una clase con <code>Zend_Form_Decorator</code> para que realizará estos cambios automáticamente, pero eso es ya lo dejo para otro post. Así que hasta aquí la primera parte de los <strong>Decorators</strong>, otro día (espero) veremos como tratar otros elementos, los errores, etc&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.backtheweb.com/zend-framework/zend-form-decorator-parte-i.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Zend Layout y ActionStacks de Zend Framework</title>
		<link>http://www.backtheweb.com/zend-framework/zend-layout-actionstacks-zend-framework.html</link>
		<comments>http://www.backtheweb.com/zend-framework/zend-layout-actionstacks-zend-framework.html#comments</comments>
		<pubDate>Tue, 29 Sep 2009 23:16:22 +0000</pubDate>
		<dc:creator>Jordi Touza Bonnin</dc:creator>
				<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://www.backtheweb.com/?p=325</guid>
		<description><![CDATA[En la documentación deZend Layout no acaba de quedar muy claro como se usa y suele provocar muchas confusiones si solo hacemos una lectura vertical del manual. Zend Layout es uno de mis objetos preferidos por la versatilidad que ofrece y una vez entiendes el proceso y como combinarlo con el resto del Framework y [...]]]></description>
			<content:encoded><![CDATA[<p>En la documentación de<strong>Zend Layout</strong> no acaba de quedar muy claro como se usa y suele provocar muchas confusiones si solo hacemos una lectura vertical del manual.</p>
<p><strong>Zend Layout</strong> es uno de mis objetos preferidos por la versatilidad que ofrece y una vez entiendes el proceso y como combinarlo con el resto del Framework y los <em>placeholders</em> obtienes una gestión muy clara de las plantillas.</p>
<p>Vamos a suponer el siguiente <em>layout</em>:</p>
<pre><code>&lt;div&gt;
&lt;?php echo $this-&gt;render('header.phtml') ?&gt;
&lt;h1&gt;&lt;?php echo $this-&gt;placeholder('h1') ?&gt;&lt;/h1&gt;
&lt;?php echo $this-&gt;layout()-&gt;nav ?&gt;
&lt;?php echo $this-&gt;layout()-&gt;content ?&gt;
&lt;/div&gt;</code></pre>
<p><span id="more-325"></span>Cada bloque de código <strong>php</strong> realiza una acción diferente.</p>
<ul>
<li><em>$this-&gt;render(&#8216;header.phtml&#8217;) </em> se encargará de llamar al archivo <em>header.phtml</em> que estará ubicado en el mismo nivel que el <em>layout</em>.</li>
<li><em>$this-&gt;placeholder(&#8216;h1&#8242;) </em> nos devolverá el valor que hallamos definido en la plantilla usando <em>$this-&gt;placeholder(&#8216;h1&#8242;)-&gt;set(&#8216;Mi h1&#8242;); </em></li>
<li><em>$this-&gt;layout()-&gt;nav</em> es un <strong>ActionStack</strong></li>
<li><em>$this-&gt;layout()-&gt;content</em> nos devolverá el contenido de la plantilla</li>
</ul>
<p>Pero ¿Que són los <em>ActionStacks</em>? ¿como se usan los? y ¿Para que sirven? Básicamente lo que logramos con los <em>ActionStacks</em> es renderizar un fragmento de código generado por una acción que no es la misma que estamos ejecutando en el momento de renderizar la página.</p>
<p>Todo será más fácil si usamos el <abbr title="Modelo Vista Controlador">MVC</abbr> o <em>Zend Application</em></p>
<p>Para hacer un <em>ActionStack</em> necesitaremos dos cosas: Un controlador y una llamada a este.</p>
<p>Lo primero será crear un controlador como cualquier otro, por ejemplo: <em>NavegacionController</em> con una acción <em>menuAction</em>. Esta acción renderizará <em>menu.phtml</em> pero le indicaremos en que segmento de la plantilla o layout se deberá renderizarse:</p>
<pre><code>
class NavegacionController extends Zend_Controller_Action{

    public function menuAction(){

    	// renderiza menu.phtml en el segmento nav
    	$this-&gt;_helper-&gt;viewRenderer-&gt;setResponseSegment('nav');
    }
}
</code></pre>
<p>Lo siguiente es hacer la llamada desde la acción principal.</p>
<pre><code>
class IndexController extends Zend_Controller_Action {

	public function indexAction() {

		$this-&gt;_helper-&gt;actionStack ('menu', 'navegacion', 'default');
	}
}
</code></pre>
<p>Es decir, cuando llamemos a <em>IndexAction</em> del <em>IndexController</em> el se encargará de llamar a <em>menuAction</em> del <em>navegaciónController</em> para que renderize <em>scripts/navegacion/menu.phtml</em> en el segmento <em>nav</em> que hemos indicado en el <em>layout</em> con <em>$this-&gt;layout()-&gt;nav</em>.</p>
<p>Entonces vemos que el primer parámetro es la acción, el segundo el controlador y el tercero es opcional y se refiere al módulo que por defecto es <em>default</em>.</p>
<p>Para profundizar más con los <em>layouts</em> estan los <em>Placeholder Helper</em> pero esto se sale ya del tema y lo dejo para otro post.</p>
<p>Espero que os se útil.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.backtheweb.com/zend-framework/zend-layout-actionstacks-zend-framework.html/feed</wfw:commentRss>
		<slash:comments>60</slash:comments>
		</item>
		<item>
		<title>Zend Framework no funciona en MAMP PRO</title>
		<link>http://www.backtheweb.com/zend-framework/zend-framework-no-funciona-en-mamp-pro.html</link>
		<comments>http://www.backtheweb.com/zend-framework/zend-framework-no-funciona-en-mamp-pro.html#comments</comments>
		<pubDate>Thu, 03 Sep 2009 21:39:12 +0000</pubDate>
		<dc:creator>Jordi Touza Bonnin</dc:creator>
				<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://www.backtheweb.com/?p=317</guid>
		<description><![CDATA[Pues hoy me he de comer las palabras que dije ayer en el post que hablaba de MAMP. Hoy he querido probar MAMP Pro y me ha decepcionado. A diferencia de la versión lite, con la Pro puedes configurar los virtual hosts sin tocar ningún fichero de conflagración ni el fichero hosts lo cual resulta [...]]]></description>
			<content:encoded><![CDATA[<p>Pues hoy me he de comer las palabras que dije ayer en el post que hablaba de <a title="MAMP, Mac Apache MySQL PHP, la mejor alternativa siempre" href="http://www.backtheweb.com/general/mamp-mac-apache-mysql-php-la-mejor-alternativa-siempre.html">MAMP</a>. Hoy he querido probar <strong>MAMP Pro</strong> y me ha decepcionado.</p>
<p>A diferencia de la versión <em>lite</em>, con la <em>Pro </em>puedes configurar los <em>virtual hosts</em> sin tocar ningún fichero de conflagración ni el fichero <em>hosts</em> lo cual resulta muy práctico cuando no te mueves con soltura por la <em>Terminal</em>.</p>
<p>El problema en cuestión ha sido un &#8220;<strong>Fatal error</strong>: <em>Allowed memory size of </em>&#8230;&#8221; al ejecutar una apalicación desarrollada en <strong>Zend Framework</strong>. Por defecto <strong>PHP </strong>establece un máximo memoria de 8 Mb y cambiar este valor es tan fácil como editar el parámetro  <em>memory_limit</em> el <em>php.ini</em>.</p>
<p><span id="more-317"></span></p>
<p>Considero que este tipo de ajustes no se deberían realizar a menos que sean realmente necesarios como cuando trabajas con imágenes pero al ser un desarrollo local tampoco es que me mporte mucho así que he editado el <em>php.ini</em>.</p>
<p>¿Cual ha sido la sorpresa? Por mucho que editará el fichero no se reflejaban los cambios. Consulto la ubicación del <em>php.ini</em> con <em>phpInfo()</em> y veo que el fichero esta ubicado en:</p>
<pre>/Library/Application Support/living-e/MAMP PRO/conf/php.ini</pre>
<p>Ok, soy tonto, estaba tocando el fichero <strong>MAMP</strong> y no de <strong>MAMP Pro</strong> (costumbre de usar la verión <em>lite)</em> así que edito el fichero correcto y reinicio.</p>
<p>¿Otra vez? Nada, no se refleja el cambio  8 por 12 y nada. Sigue en 8Mb. La cosa estaba clara yo editaba el fichero correcto pero al arrancar <strong>MAMP Pro</strong> se sobrescribe los cambios. Por lo tanto el fichero <em>php.ini</em> esta en otro lugar y no podía ser otro que dentro de la misma aplicación.</p>
<p>Entonces es cuando abro el contenido de <strong>MAMP Pro</strong> y encuentro el fichero correcto en:</p>
<pre>/Applications/MAMP PRO 1.72/MAMP PRO.app/Contents/Resources/php5.ini</pre>
<p>Ok, todo listo, reiniciamos el <strong>Apache</strong> y comprobamos que los ajustes sean correctos. Y lo son, pero nada el <strong>Fatal Error </strong>aparece igualmente por lo que acabo subiendo el limite de memoria a 32Mb pero nada.</p>
<p>La conclusión es <strong>Zend Framework</strong> no funciona en <strong>MAMP Pro</strong>. Quizás no he buscado suficientemente bien en <em>Google</em>, pero si empezamos así.. mejor volver a usar <a title="MacPorts" href="http://www.macports.org/">MacPorts</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.backtheweb.com/zend-framework/zend-framework-no-funciona-en-mamp-pro.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Como manejar fechas en Zend Framework con Zend Form y Zend Validate</title>
		<link>http://www.backtheweb.com/zend-framework/como-manejar-fechas-en-zend-framework-con-zend-form-y-zend-validate.html</link>
		<comments>http://www.backtheweb.com/zend-framework/como-manejar-fechas-en-zend-framework-con-zend-form-y-zend-validate.html#comments</comments>
		<pubDate>Sun, 30 Aug 2009 08:00:16 +0000</pubDate>
		<dc:creator>Jordi Touza Bonnin</dc:creator>
				<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://www.backtheweb.com/?p=271</guid>
		<description><![CDATA[Validar una fecha en un formulario usando los módulos Zend Form y Zend Validate no tiene ningún misterio tan solo deberemos agregar la clase Zend_Validate_Date a la opción valdators de nuestro elemento tipo text del fomulario, algo así: $form-&#62;addElement('text', 'date', array( 'label' =&#62; 'date', 'validators' =&#62; array('date') )); El problema lo encontramos cuando queremos usar [...]]]></description>
			<content:encoded><![CDATA[<p>Validar una fecha en un formulario usando los módulos <strong>Zend Form</strong> y <strong>Zend Validate</strong> no tiene ningún misterio tan solo deberemos agregar la clase <strong>Zend_Validate_Date</strong> a la opción <em>valdators</em> de nuestro elemento tipo <em>text</em> del fomulario, algo así:</p>
<pre><code> $form-&gt;addElement('text', 'date', array( 'label' =&gt; 'date', 'validators' =&gt; array('date') )); </code></pre>
<p>El problema lo encontramos cuando queremos usar un determinado formato de fecha y lo queremos almacenar en la base de datos. Este tipo de tareas son las que un programador siempre recopila en una función y se las guarda en su librería para facilitarse la tareas repetitivas en sus proyectos. En cierto modo estas tareas ya las hacen o deberían hacer los <strong>frameworks</strong> (pues los <em>frameworks</em> son al final una recopliación de funciones y clases para facilitarnos el trabajo).</p>
<p><span id="more-271"></span></p>
<p>En el <strong>Zend Framework</strong> no existe por ahora una forma muy clara de como automatizar este proceso si usamos el módulo <strong>Zend Application</strong> pero con un par de apaños y sin usar ningún <em>plugin</em> o <em>helper</em> veamos como lo podemos solucionar con lo que nos ofrece el <em>framework</em></p>
<p>Primeros, vamos a suponer que estamos creando una aplicación con la misma estructura que se usa en el <em>Quick Start</em> del <strong>Zend Framework</strong>. Entonces ¿Que neceistamos?</p>
<ul>
<li>
<ol>
<ol>Un objeto de formulario</ol>
</ol>
<p><strong>Zend_Form</strong></p>
<ol>
<ol>Un modelo de datos</ol>
</ol>
<p><strong>Zend_DB_Table</strong></p>
<ol>y un mapeador</ol>
<ol>
<ol>internacionalizar la aplicación con</ol>
</ol>
<p><strong>Zend_Locale</strong></li>
</ul>
<p>¿Por dónde empezamos?<br />
Lo primero que haremos será que nuestro formulario valide las fechas con el formato que a nosotros nos interesa <em>dd/mm/yyyy</em> (es decir el más común en la lengua hispánica). Para ello en nuestra objeto formulario que extiende el <strong>Zend_Form</strong> debe existir un elemento tipo texto para introducir la fecha:</p>
<pre><code> $this-&gt;addElement('text', 'fecha', array( 'label' =&gt; 'fecha', 'required' =&gt; true, 'filters' =&gt; array('StringTrim', 'StripTags'), 'validators' =&gt; array('date') ));</code></pre>
<p>Lo que estamos haciendo es que solo las fechas serán validas pero no estamos indicando en que formato. Aquí es cuando entra en juego <strong>Zend Locale</strong> por lo que añdiremos en nuestro <em>bootstrap</em> la siguiente función:</p>
<pre><code> protected function _initLocale(){ $locale = new Zend_Locale(); $locale-&gt;setLocale('es_ES'); Zend_Registry::set('Zend_Locale', $locale); // la registramos para su futuro uso en el resto de la aplicación } </code></pre>
<p>Una vez la fecha es valida la hemos de guardar en la base de datos con el formato tipico de <em>yyyy-mm-dd</em>. Nos situamos en la función <em>Save</em> de nuestro <em>mapper</em> y añadiremos al principio la conversión de tipo de fecha con <strong>Zend_date</strong>:</p>
<pre><code> public function save(Default_Model_Mitabla $tabla){ // Creamos un objeto Zend_Date y como parámetro la fecha que recibimos $fecha = new Zend_Date($tabla-&gt;getFecha()); $data = array( 'nombre' =&gt; $tabla-&gt;getNombre(), 'startDate' =&gt; $startDate-&gt;getIso() // retornamos la fecha en formato ISO 8601 ); if (null === ($id = $tabla-&gt;getId()) || $tabla-&gt;getID() == 0) { unset($data['id']); $this-&gt;getDbTable()-&gt;insert($data); } else { $this-&gt;getDbTable()-&gt;update($data, array('id = ?' =&gt; $id)); } } </code></pre>
<p>Finalmente solo nos queda una cosa, recuperar las fechas de la base de datos en el formato que deseamos, por lo que modificaremos la función <em>Find</em> del <em>mapper</em>:</p>
<pre><code> public function find($id, Default_Model_Mitabla $tabla){ $result = $this-&gt;getDbTable()-&gt;find($id); if (0 == count($result)) { return; } $row = $result-&gt;current(); $fecha = new Zend_Date($row-&gt;fecha, Zend_Date::ISO_8601); $job-&gt;setId($row-&gt;id) -&gt;setNombre($row-&gt;nombre) -&gt;setStartDate(str_replace('00:00:00', '', $fecha-&gt;getDate())); } </code></pre>
<p>Nuevamente lo que hacemos es crear un objeto <strong>Zend Date</strong> pasando como primer argumento la fecha que recibimos de la base de datos y como segundo el formato en que la recibimos. Luego con <em>getDate()</em> devolvemos la fecha en el formato esperado tal como hemos indicado con <strong>Zend_Locale</strong>. Notad que he añadido un <em>str_replace</em> pues como se trata de un campo de tipo <em>Date</em> y no <em>Datetime</em> no me interesa que me retorne la hora.</p>
<p>De esta forma, en principio, nos será fácil mantener una aplicación en diferentes idiomas y las fechas se mostraran en el formato propio del idioma indicado, prueba a cambiar el argumento <em>locale</em> del objeto <strong>&gt;Zend Locale y todo debería funcionar correctamente.</strong></p>
<p><strong>Espero que os sea útil y se veis algún error o sabéis la forma de hacerlo mucho más fácil espero vuestros comentarios.</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://www.backtheweb.com/zend-framework/como-manejar-fechas-en-zend-framework-con-zend-form-y-zend-validate.html/feed</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Como activar los helpers con Zend_Application</title>
		<link>http://www.backtheweb.com/zend-framework/como-activar-los-helpers-con-zend_application.html</link>
		<comments>http://www.backtheweb.com/zend-framework/como-activar-los-helpers-con-zend_application.html#comments</comments>
		<pubDate>Sat, 22 Aug 2009 17:47:06 +0000</pubDate>
		<dc:creator>Jordi Touza Bonnin</dc:creator>
				<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://www.backtheweb.com/?p=244</guid>
		<description><![CDATA[Últimamente le encuentro más pegas que ventajas al modulo Zend_Application que incorpora la versión 1.9 del Zend Framework. Esta vez se trata de los helpers. El primer problema lo encontramos a la hora de construir la aplicación con Zend_Tool, pues este no crear la carpeta pertinente. Y esto nos lleva al segundo problema y es [...]]]></description>
			<content:encoded><![CDATA[<p>Últimamente le encuentro más pegas que ventajas al modulo <strong>Zend_Application</strong> que incorpora la versión 1.9 del <strong>Zend Framework</strong>. Esta vez se trata de los <strong>helpers</strong>.</p>
<p>El primer problema lo encontramos a la hora de construir la aplicación con <strong>Zend_Tool</strong>, pues este no crear la carpeta pertinente. Y esto nos lleva al segundo problema y es que <strong>Zend_Tool</strong> no registra el lugar donde serán llamados los <strong>helpers</strong>.<br />
<span id="more-244"></span><br />
Entonces lo primero que hemos de hacer es crear la carpeta<strong> helpers</strong>. ¿Dónde? En principio donde queramos. Lo lógico sería crearla dentro de la carpeta <em>controllers</em>, pero si usamos el <strong>Zend Studio</strong> cuando queramos crear un <em>helper</em> nos  lo pondrá en la raíz porque el lugar por defecto para crear los <strong>helpers </strong>es dentro de <em>application</em> es decir: <em>/application/helpers</em>.</p>
<p>Lo segundo que hemos de hacer es añadir al <em>bootstrap</em> la siguiente linea (teniendo en cuenta que existe la constante <em>APPLICATION_PATH</em> que es la ruta de nuestra aplicación y que queremos guardar los <strong>helpers</strong> en <em>/application/helpers):</em></p>
<pre><code> Zend_Controller_Action_HelperBroker::addPath(APPLICATION_PATH .'/helpers'); </code></pre>
<p>&nbsp;</p>
<p>Pero existe otro problema aún si usamos diferentes módulos dentro de nuestra aplicación. Seguramente nos interesará que cada módulo tenga sus propios <strong>helpers</strong></p>
<p>Para ello debemos hacer algo parecido a lo que vimos en un post anterior <a href="http://www.backtheweb.com/php/zend-framework-como-hacer-un-layout-para-cada-modulo.html">como hacer un layout para cada modulo</a></p>
<p>Necesitaremos crear un <strong>plugin</strong>:</p>
<pre><code> //My/Controller/Action/helpers.php class My_Controller_Action_helpers extends Zend_Controller_plugin_Abstract{ public function preDispatch(Zend_Controller_Request_Abstract $request){ $config = Zend_Controller_Front::getInstance()-&gt;getParam('bootstrap')-&gt;getOptions(); $moduleName = $request-&gt;getModuleName(); Zend_Controller_Action_HelperBroker::addPath(APPLICATION_PATH . '/modules/' . $moduleName . '/helpers'); } } </code></pre>
<p>y luego registrarlo en el <em>bootstrap</em>:</p>
<pre><code> protected function _initPlugins(){ $this-&gt;bootstrap('frontController'); $plugin = new My_Controller_Action_Helpers(); $this-&gt;frontController-&gt;registerPlugin($plugin); Zend_Controller_Action_HelperBroker::addPath(APPLICATION_PATH . '/helpers'); } </code></pre>
<p>En mi caso para no crear dos plugins tan solo he añadido la linea de llamada a <em>Zend_Controller_Action_HelperBroker</em> al plugin que ya había creado en el post anterior mencionado.</p>
<p>Buenos espero que os sea útil.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.backtheweb.com/zend-framework/como-activar-los-helpers-con-zend_application.html/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Zend framework, como hacer un layout para cada modulo</title>
		<link>http://www.backtheweb.com/zend-framework/zend-framework-como-hacer-un-layout-para-cada-modulo.html</link>
		<comments>http://www.backtheweb.com/zend-framework/zend-framework-como-hacer-un-layout-para-cada-modulo.html#comments</comments>
		<pubDate>Mon, 10 Aug 2009 23:37:50 +0000</pubDate>
		<dc:creator>Jordi Touza Bonnin</dc:creator>
				<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.backtheweb.com/?p=211</guid>
		<description><![CDATA[Si estas usando la última versión de Zend Framework, la 1.9.0, y usas Zend_Application para crear aplicaciones modulares habrás notado que no puedes asignar un layout diferente para cada modulo. Después de buscar y probar diferentes métodos algunos muy complejos y que no se muy bien porque no me funcionaban encontré la solución mezclando todo [...]]]></description>
			<content:encoded><![CDATA[<p>Si estas usando la última versión de <strong>Zend Framework</strong>, la 1.9.0, y usas <strong>Zend_Application</strong> para crear aplicaciones modulares habrás notado que no puedes asignar un <em>layout</em> diferente para cada modulo. Después de buscar y probar diferentes métodos algunos muy complejos y que no se muy bien porque no me funcionaban encontré la solución mezclando todo lo que había visto.</p>
<p>Vamos a suponer que queremos crear un modulo <em>Admin </em>para nuestra aplicación y que usamos la jerarquía de ficheros establecida con <strong>Zend Tool</strong>. Seguramente nuestro fichero <em>application.ini</em> empezará algo similar a esto:<br />
<span id="more-211"></span></p>
<pre class="prettyprint"><code class="language-php">[production] phpSettings.display_startup_errors = 0 phpSettings.display_errors = 0 includePaths.library = APPLICATION_PATH "/../library" bootstrap.path = APPLICATION_PATH "/Bootstrap.php" bootstrap.class = "Bootstrap" resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts" resources.layout.layout = layout resources.view[] = resources.view.basePath = APPLICATION_PATH "/views/"</code></pre>
<p>Y probablemente querremos añadir un par de lineas para que nuestro <em>Admin</em> tenga su propio <em>layout</em>.</p>
<pre class="prettyprint"><code class="language-php">;Modules config resources.frontController.moduleDirectory = APPLICATION_PATH "/modules" admin.resources.layout.layoutPath = APPLICATION_PATH "/modules/admin/layouts/scripts" admin.resources.layout.layout = layout</code></pre>
<p>Claro esta que eso no es suficiente, deberemos añadir:</p>
<pre class="prettyprint"><code class="language-php">resources.modules[] =</code></pre>
<p>Este debe ser el primer recurso que cargues, de otra forma no funcionará, para ello colócalo al principio de todo, justo por debajo de <em>[production]</em>.</p>
<p>Seguramente, todo esto ya lo has echo y sabes que no funciona, que lo que sucede es que se sobrescribirá el <em>resources.layout.layoutPath</em> y no funcionará. Por ello lo que necesitamos es un <em>Plugin</em> que nos cargue el <em>layout</em> correcto:</p>
<pre class="prettyprint"><code class="language-php">// My/Controller/Plugin/Layout.php
class My_Controller_Plugin_Layout extends Zend_Controller_plugin_Abstract{
public function preDispatch(Zend_Controller_Request_Abstract $request){
$config = Zend_Controller_Front::getInstance()-&gt;getParam('bootstrap')-&gt;getOptions();
$moduleName = $request-&gt;getModuleName();
if (isset($config[$moduleName]['resources']['layout']['layout'])) {
$layoutScript = $config[$moduleName]['resources']['layout']['layout'];
Zend_Layout::getMvcInstance()-&gt;setLayout($layoutScript);
}
if (isset($config[$moduleName]['resources']['layout']['layoutPath'])) {
$layoutPath = $config[$moduleName]['resources']['layout']['layoutPath'];
$moduleDir = Zend_Controller_Front::getInstance()-&gt;getModuleDirectory();
Zend_Layout::getMvcInstance()-&gt;setLayoutPath($layoutPath);
}
}
}</code></pre>
<p>Y a continuación añadimos a nuestro <em>Bootstrap.php</em>:</p>
<pre class="prettyprint"><code class="language-php">protected function _initPlugins(){ $this-&gt;bootstrap('frontController'); $plugin = new My_Controller_Plugin_Layout(); $this-&gt;frontController-&gt;registerPlugin($plugin); }</code></pre>
<p>Con esto lo que hacemos es que registrar el <em>plugin</em> para que sea interpretado por el <strong>Zend Framework</strong></p>
<p>Dado que he usado el <em>namespace</em> <em>My</em> necesitaré registrarlo en el fichero <em>application.ini</em> añadiendo la siguiente linea:</p>
<pre class="prettyprint"><code class="language-php">autoloaderNamespaces[] = "My"</code></pre>
<p>De esta forma mi <em>application.ini</em> de la aplicación, no del módulo quedaría así:</p>
<pre class="prettyprint"><code class="language-php">[production] ;First resource to load resources.modules[] = phpSettings.display_startup_errors = 0 phpSettings.display_errors = 0 includePaths.library = APPLICATION_PATH "/../library" autoloaderNamespaces[] = "My" bootstrap.path = APPLICATION_PATH "/Bootstrap.php" bootstrap.class = "Bootstrap" resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers" resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts" resources.layout.layout = layout resources.view[] = resources.view.basePath = APPLICATION_PATH "/views/" ;Modules config resources.frontController.moduleDirectory = APPLICATION_PATH "/modules" admin.resources.layout.layoutPath = APPLICATION_PATH "/modules/admin/layouts/scripts" admin.resources.layout.layout = layout</code></pre>
<p>Y listo, ya tenemos asignado un <em>layout</em> diferente para nuestro <em>Admin</em>. Para mejorar todo esto sería bueno que las especificaciones de cada módulo se declararán en el fichero <em>application.ini</em> de cada módulo, pero para eso necesitariamos crear un <em>Resource</em> que interpretará cada fichero por separado.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.backtheweb.com/zend-framework/zend-framework-como-hacer-un-layout-para-cada-modulo.html/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
	</channel>
</rss>

