<?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>TecnoRetales &#187; Frameworks</title>
	<atom:link href="http://www.tecnoretales.com/categoria/frameworks/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.tecnoretales.com</link>
	<description>La experiencia no se olvida</description>
	<lastBuildDate>Mon, 13 Sep 2010 21:37:21 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
		<!-- google ad injected by adsense-optimizer http://www.adsenseoptimizer.de -->
			<div  style="padding:7px; float: right; padding-right: 0; margin: 3px;"><!-- Ad number: 1 --><script type="text/javascript"><!--
    	 
    	google_ad_client = "pub-7180773421652966"; google_alternate_color = "FFFFFF";
		google_ad_width = 468; google_ad_height = 60;
		google_ad_format = "468x60_as"; google_ad_type = "text";
		google_ad_channel =""; google_color_border = "FE8B00";
		google_color_link = "FE8B00"; google_color_bg = "FFFFFF";
		google_color_text = "000000"; google_color_url = "D9D9D9";
		google_ui_features = "rc:6"; //--></script>
		<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script></div>	<item>
		<title>Smarty3 y autoload</title>
		<link>http://www.tecnoretales.com/programacion/smarty3-y-autoload/</link>
		<comments>http://www.tecnoretales.com/programacion/smarty3-y-autoload/#comments</comments>
		<pubDate>Tue, 29 Jun 2010 07:41:32 +0000</pubDate>
		<dc:creator>Manel Pérez Mata</dc:creator>
				<category><![CDATA[Frameworks]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[Smarty]]></category>

		<guid isPermaLink="false">http://www.tecnoretales.com/?p=741</guid>
		<description><![CDATA[
Uno de los errores comunes al implementar Smarty3 es:
Fatal error: Class &#8216;Smarty_Internal_Wrapper&#8217; not found
Fatal error: Class &#8216;Smarty_Internal_Register&#8217; not found
Fatal error: Class &#8216;Smarty_Internal_Template&#8217; not found
Estos se deban, probablemente, a que en tu aplicación estás utilizando la función __autoload también necesaria por Smarty3. La solución a este problema pasa por utilizar la función que PHP nos brinda [...]]]></description>
			<content:encoded><![CDATA[<!-- google_ad_section_start --><p><img class="size-full wp-image-74 alignright" src="http://www.tecnoretales.com/wp-content/uploads/2009/05/logo_smarty.gif" alt="Smarty Logo" width="250" height="64" /></p>
<p>Uno de los errores comunes al <strong>implementar Smarty3</strong> es:</p>
<blockquote><p>Fatal error: Class &#8216;Smarty_Internal_Wrapper&#8217; not found</p>
<p>Fatal error: Class &#8216;Smarty_Internal_Register&#8217; not found</p>
<p>Fatal error: Class &#8216;Smarty_Internal_Template&#8217; not found</p></blockquote>
<p>Estos se deban, probablemente, a que en tu aplicación estás utilizando la función <strong>__autoload</strong> también necesaria por Smarty3. La solución a este problema pasa por utilizar la función que PHP nos brinda <strong>spl_autoload_register</strong>.</p>
<p>En una aplicación, sólo puede existir una llamada a la función __autload, sin embargo, con spl_autoload_register podemos añadir tantos manejadores como queramos y estos se irán ejecutando en el orden en el que los hayamos registrado.</p>
<p>Un ejemplo sencillo de su uso sería:</p>
<pre class="brush: php;">

class AutoloadHandler
{
	static public function launch( $classname )
	{
		print '[['. $name .']]';
	}
}

spl_autoload_register( 'AutoloadHandler::launch' );

new ThisClassNotExists();
</pre>
<p>El resultado de ejecutar este script sería algo así:</p>
<blockquote><p>[[ThisClassNotExists]]</p>
<p>Fatal error: Class &#8216;ThisClassNotExists&#8217; not found in &#8230;</p></blockquote>
<p>El cual nos indica que está llamando de manera correcta al autoload, pero al no estar implementado de manera correcta y no existir la clase &#8216;ThisClassNotExists&#8217; nos devuelve un error.</p>
<p>En definitiva, <strong>para solventar el problema</strong>, no será necesario que modifiques el código Smarty, pues este ya está utilizando de manera correcta spl_autoload_register, lo que debes hacer es <strong>sustituir tu __autoload</strong> por una clase con una función &#8216;launch&#8217; (llámala como quieras) y registrarla mediante:</p>
<pre class="brush: php;">
&amp;amp;lt;pre&amp;amp;gt;spl_autoload_register( 'MyAutoloadHandler::launch' );&amp;amp;lt;/pre&amp;amp;gt;
</pre>
<!-- google_ad_section_end -->]]></content:encoded>
			<wfw:commentRss>http://www.tecnoretales.com/programacion/smarty3-y-autoload/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Smarty3 y gettext</title>
		<link>http://www.tecnoretales.com/programacion/smarty3-y-gettext/</link>
		<comments>http://www.tecnoretales.com/programacion/smarty3-y-gettext/#comments</comments>
		<pubDate>Sat, 26 Jun 2010 07:39:32 +0000</pubDate>
		<dc:creator>Manel Pérez Mata</dc:creator>
				<category><![CDATA[Frameworks]]></category>
		<category><![CDATA[Programación]]></category>

		<guid isPermaLink="false">http://www.tecnoretales.com/?p=732</guid>
		<description><![CDATA[Si estás utilizando Smarty2 y te has decidido a dar el salto a Smarty3 para aprovecharte de sus nuevas funcionalidades (como por ejemplo la nada despreciable opción de herencia en templates), verás que existen algunas incompatibilidades, por ejemplo, se han decidido por seguir el estandar camelCase en el nombre de las funciones, utilizan getters y [...]]]></description>
			<content:encoded><![CDATA[<!-- google_ad_section_start --><p>Si estás utilizando Smarty2 y te has decidido a dar el salto a Smarty3 para aprovecharte de sus nuevas funcionalidades (como por ejemplo la nada despreciable opción de herencia en templates), verás que existen algunas incompatibilidades, por ejemplo, se han decidido por seguir el estandar camelCase en el nombre de las funciones, utilizan getters y setters para los atributos o han cambiado la manera de registrar bloques.</p>
<p>En el caso del popular plugin <strong>smarty-gettext</strong>, si tenemos personalizada la llamada al traductor con, por ejemplo &#8216;{t}&#8217; como es mi caso, nos encontraremos con un bonito error:</p>
<blockquote><p>function call &#8216;register_block&#8217; is unknown or deprecated</p></blockquote>
<p>Esto es debido a que la forma correcta de registrar bloques en Smarty3 es:</p>
<pre class="brush: php;">

$this-&gt;register-&gt;block('t', 'translate');
</pre>
<p>en lugar de:</p>
<pre class="brush: php;">

$this-&gt;register_block( 't', 'translate' );
</pre>
<p>Una vez hecho esto, el siguiente error que nos deja Smarty es:</p>
<blockquote><p>Plugin &#8220;t&#8221; not callable</p></blockquote>
<p>En lugar del antiguo &#8216;translate&#8217;, el segundo parámetro deberá ser el nombre correcto de la función, es decir &#8217;smarty_translate&#8217;:</p>
<pre class="brush: php;">

$this-&gt;register-&gt;block('t', 'smarty_translate');
</pre>
<p>de este modo solventaremos el problema y podremos seguir disfrutando de nuestro plugin de traducción.</p>
<!-- google_ad_section_end -->]]></content:encoded>
			<wfw:commentRss>http://www.tecnoretales.com/programacion/smarty3-y-gettext/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Symfony: Upgrade de 1.2.x a 1.4 con PEAR</title>
		<link>http://www.tecnoretales.com/programacion/symfony-upgrade-de-1-2-x-a-1-4-con-pear/</link>
		<comments>http://www.tecnoretales.com/programacion/symfony-upgrade-de-1-2-x-a-1-4-con-pear/#comments</comments>
		<pubDate>Thu, 10 Dec 2009 17:55:15 +0000</pubDate>
		<dc:creator>Manel Pérez Mata</dc:creator>
				<category><![CDATA[Frameworks]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://www.tecnoretales.com/?p=722</guid>
		<description><![CDATA[Antes de empezar a hacer el upgrade de symfony debemos asegurarnos que los plugins utilizados actualmente en el proyecto son compatibles con la versión 1.4, en caso de no ser compatibles, tenemos tres opciones:

Buscar un plugin similar que sí sea compatible.
Modificar nuestra aplicación para que no utilice dicho plugin.
Si no podemos prescindir de él, habrá [...]]]></description>
			<content:encoded><![CDATA[<!-- google_ad_section_start --><p>Antes de empezar a hacer el <strong>upgrade de symfony</strong> debemos asegurarnos que los plugins utilizados actualmente en el proyecto son compatibles con la <strong>versión 1.4</strong>, en caso de no ser compatibles, tenemos tres opciones:</p>
<ol>
<li>Buscar un plugin similar que sí sea compatible.</li>
<li>Modificar nuestra aplicación para que no utilice dicho plugin.</li>
<li>Si no podemos prescindir de él, habrá que esperar a que saquen la compatibilidad o hackearlo nosotros mismos (lo qual podría ser muy fácil o muy difícil en función del tipo de problema).</li>
</ol>
<p>Pasos a seguir para subir de versión:</p>
<p>1) Update de los canales de pear</p>
<p style="padding-left: 30px;"><em>sudo pear update-channels</em></p>
<p>2) Upgrade de symfony a la versión 1.3</p>
<p style="padding-left: 30px;"><em>sudo pear upgrade -f symfony/symfony-1.3.0</em></p>
<p>3) Validamos que no estamos usando métodos deprecated (estós están eliminados en la <strong>versión 1.4</strong>)</p>
<p style="padding-left: 30px;"><em>symfony project:validate</em></p>
<p>En caso de obtener errores del validador, los solventaremos antes de hacer el upgrade siguiendo instrucciónes en la página <a title="Symfony deprecations and removals in 1.3" href="http://www.symfony-project.org/tutorial/1_4/en/deprecated" target="_blank">Deprecations and removals in 1.3</a></p>
<p>4) Upgrade del projecto a la versión 1.3</p>
<p style="padding-left: 30px;"><em>symfony project:upgrade1.3</em></p>
<p>5) Upgrade de los plugins a la última versión</p>
<p style="padding-left: 30px;"><em>symfony plugin:upgrade [plugin]</em></p>
<p>6) Upgrade de symfony a la última versión</p>
<p style="padding-left: 30px;"><em>sudo pear upgrade symfony/symfony</em></p>
<p>7) Limpiamos la caché antes de probar</p>
<p style="padding-left: 30px;"><em>symfony cc</em></p>
<p>Ahora deberíamos tener nuestro proyecto updateado a la última versión estable de symfony <img src='http://www.tecnoretales.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<!-- google_ad_section_end -->]]></content:encoded>
			<wfw:commentRss>http://www.tecnoretales.com/programacion/symfony-upgrade-de-1-2-x-a-1-4-con-pear/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	<!-- google ad injected by adsense-optimizer http://www.adsenseoptimizer.de -->
			<div  style="padding:7px; float: left; padding-left: 0px; margin: 3px;"><!-- Ad number: 2 --><script type="text/javascript"><!--
    	 
    	google_ad_client = "pub-7180773421652966"; google_alternate_color = "FFFFFF";
		google_ad_width = 468; google_ad_height = 60;
		google_ad_format = "468x60_as"; google_ad_type = "text";
		google_ad_channel =""; google_color_border = "FE8B00";
		google_color_link = "FE8B00"; google_color_bg = "FFFFFF";
		google_color_text = "000000"; google_color_url = "D9D9D9";
		google_ui_features = "rc:6"; //--></script>
		<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script></div>	<item>
		<title>Symfony i18n con gettext</title>
		<link>http://www.tecnoretales.com/programacion/symfony-i18n-con-gettext/</link>
		<comments>http://www.tecnoretales.com/programacion/symfony-i18n-con-gettext/#comments</comments>
		<pubDate>Sat, 05 Dec 2009 14:26:01 +0000</pubDate>
		<dc:creator>Manel Pérez Mata</dc:creator>
				<category><![CDATA[Frameworks]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://www.tecnoretales.com/?p=716</guid>
		<description><![CDATA[Symfony permite varios métodos para internazionalizar nuestra aplicación. Por defecto, utilizan el formato XLIFF sin embargo, personalmente me gusta más gettext.
¿Cómo configurar symfony para usar gettext?
Para configurar symfony para que utilice gettext seguiremos los siguientes pasos:
1) Activamos el módulo I18N modificando el archivo settings.yml:
#apps/&#60;appName&#62;/config/settings.yml
all:
  .settings:
    charset:      [...]]]></description>
			<content:encoded><![CDATA[<!-- google_ad_section_start --><p>Symfony permite varios métodos para <strong>internazionalizar</strong> nuestra aplicación. Por defecto, utilizan el <a title="Formato XLIFF" href="http://es.wikipedia.org/wiki/XLIFF" target="_blank">formato XLIFF</a> sin embargo, personalmente me gusta más <a title="Gettext" href="http://es.wikipedia.org/wiki/Gettext" target="_blank">gettext</a>.</p>
<p><strong>¿Cómo configurar symfony para usar gettext?</strong></p>
<p>Para configurar symfony para que utilice <strong>gettext</strong> seguiremos los siguientes pasos:</p>
<p>1) Activamos el módulo I18N modificando el archivo <strong>settings.yml</strong>:</p>
<pre class="brush: php;">#apps/&lt;appName&gt;/config/settings.yml
all:
  .settings:
    charset:                utf-8
    i18n:                   on
    standard_helpers:       [ [TUS_HELPERS_ACTIVADOS]..., I18N]</pre>
<p>2) Abrimos el archivo <strong>factories.yml</strong> y añadimos la entrada i18n:</p>
<pre class="brush: php;">#apps/&lt;appName&gt;/config/factories.yml
all:
  i18n:
    class: sfI18N
    param:
      default_culture:  en_US
      source:           gettext&lt;/pre&gt;
</pre>
<p>3) Crearemos una carpeta i18n dentro de <em>apps/<appName>/</em>:</p>
<pre class="brush: php;">apps/&lt;appName&gt;/i18n/&lt;lang&gt;</pre>
<p>Donde &lt;lang&gt; será el idioma en dos letras (en, es, fr&#8230;) y dentro tendremos los ficheros messages.po y messages.mo.</p>
<p>Ahora podemos utilizar la función __( &#8216;texto_a_traducir&#8217; ) con doble <em>underscore</em> [ _ ] en lugar del simple utilizado normalmente.</p>
<p><strong>¿Cómo generar automáticamente nuestros ficheros po y mo?</strong></p>
<p>Symfony trae una serie de herramientas que nos permiten generar los archivos po y mo de manera automática. Invocando el comando:</p>
<p><code>symfony i18n:extract frontend en --auto-save</code></p>
<p>Se recorrerá todos los archivos php de nuestra aplicación (código y templates) y sacará los textos que encuentre en las funciones __().</p>
<p>También se puede utilizar el mismo comando de la siguiente manera:</p>
<p><code>symfony i18n:extract frontend en --auto-delete</code></p>
<p>para eliminar las cadenas de texto que ya no existen.</p>
<!-- google_ad_section_end -->]]></content:encoded>
			<wfw:commentRss>http://www.tecnoretales.com/programacion/symfony-i18n-con-gettext/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>La clase sfConfig de Symfony</title>
		<link>http://www.tecnoretales.com/programacion/la-clase-sfconfig-de-symfony/</link>
		<comments>http://www.tecnoretales.com/programacion/la-clase-sfconfig-de-symfony/#comments</comments>
		<pubDate>Sat, 10 Oct 2009 21:05:27 +0000</pubDate>
		<dc:creator>Manel Pérez Mata</dc:creator>
				<category><![CDATA[Frameworks]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://www.tecnoretales.com/?p=701</guid>
		<description><![CDATA[Aquí os dejo algo de información sobre como solicitar variables de configuración en symfony además de un listado muy útil con todas las variables que Symfony trae predefinidas.
Cómo pedir variables definidas
Se puede llamar a la función estática get del objeto sfConfig para solicitar cualquier variable definida pasándo dos valores. El primero indica el nombre de [...]]]></description>
			<content:encoded><![CDATA[<!-- google_ad_section_start --><p>Aquí os dejo algo de información sobre como solicitar variables de configuración en symfony además de un listado muy útil con todas las variables que Symfony trae predefinidas.</p>
<h3>Cómo pedir variables definidas</h3>
<p>Se puede llamar a la función estática get del objeto sfConfig para solicitar cualquier variable definida pasándo dos valores. El primero indica el nombre de la variable solicitada y el segundo, el valor que retornará en caso de no existir dicha variable.</p>
<pre><strong>sfConfig::get('sf_config_variable', 'The default value'); </strong>// The default is optional</pre>
<p><span id="more-701"></span>Además de las variables que symfony trea configuradas por defecto, podemos añadir nuestras propias variables. Esto se hace en los archivos app.yml. Tenemos un app.yml global para todas las aplicaciones y módulos de nuestro proyecto localizado en:</p>
<pre>/path/to/project/[PROJECT_NAME]/config/app.yml</pre>
<p>y otro para cada una de las aplicaciones:</p>
<pre>/path/to/project/[PROJECT_NAME]/apps/[APP_NAME]/config/app.yml</pre>
<p>NOTA! Si existen dos variables con el mismo nombre en el app.yml global y en el de aplicación, este último valor sobreescribirá el valor global.</p>
<p>Para solicitar una variable definida en uno de estos archivos app.yml devemos añadir app_ al nombre de la variable como se muestra en el siguiente ejemplo:</p>
<pre>sfConfig::get('<strong>app_</strong>sf_config_variable');</pre>
<p>Si en el archivo app.yml definimos la variable en cascada, como por ejemplo:</p>
<pre>all:
  admin:
    email: admin@mail.bla
</pre>
<p>Deberemos acceder a ella añadiendo los diferentes niveles en la llamada:</p>
<pre>sfConfig::get('<strong>app_</strong>admin_email');
También podemos acceder a los valores configurados en settings.yml añadiendo el prefijo “sf_” al valor que queremos recuperar.
</pre>
<h3>Variables definidas por Symfony Framework</h3>
<pre><strong>sf_symfony_lib_dir</strong></pre>
<p>Path real a la carpeta lib del framework:</p>
<pre>/usr/share/php/symfony/symfony12/lib</pre>
<h3>Project Structure and Layout</h3>
<pre><strong>sf_root_dir</strong></pre>
<p>Path a la raiz del projecto:</p>
<pre>/path/to/project/[PROJECT_NAME]</pre>
<pre><strong>sf_apps_dir</strong></pre>
<p>Path a la carpeta &#8220;apps&#8221; del proyecto:</p>
<pre>/path/to/project/[PROJECT_NAME]/apps</pre>
<pre><strong>sf_lib_dir</strong></pre>
<p>Path a la carpeta &#8220;lib&#8221; del proyecto:</p>
<pre>/path/to/project/[PROJECT_NAME]/lib</pre>
<pre><strong>sf_log_dir</strong></pre>
<p>Path a la carpeta &#8220;log&#8221; del proyecto:</p>
<pre>/path/to/project/[PROJECT_NAME]/log</pre>
<pre><strong>sf_data_dir</strong></pre>
<p>Path a la carpeta &#8220;data&#8221; del proyecto:</p>
<pre>/path/to/project/[PROJECT_NAME]/data</pre>
<pre><strong>sf_config_dir</strong></pre>
<p>Path a la carpeta &#8220;config&#8221; del proyecto:</p>
<pre>/path/to/project/[PROJECT_NAME]/config</pre>
<pre><strong>sf_test_dir</strong></pre>
<p>Path a la carpeta &#8220;test&#8221; del proyecto:</p>
<pre>/path/to/project/[PROJECT_NAME]/test/</pre>
<pre><strong>sf_doc_dir</strong></pre>
<p>Path a la carpeta &#8220;doc&#8221; del proyecto:</p>
<pre>/path/to/project/[PROJECT_NAME]/doc</pre>
<pre><strong>sf_plugins_dir</strong></pre>
<p>Path a la carpeta de &#8220;plugins&#8221; del proyecto:</p>
<pre>/path/to/project/[PROJECT_NAME]/plugins</pre>
<pre><strong>sf_cache_dir</strong></pre>
<p>Path a la carpeta &#8220;cache&#8221; del proyecto:</p>
<pre>/path/to/project/[PROJECT_NAME]/cache</pre>
<pre><strong>sf_web_dir</strong></pre>
<p>Path a la carpeta pública &#8220;web&#8221;:</p>
<pre>/path/to/project/[PROJECT_NAME]/web</pre>
<pre><strong>sf_upload_dir</strong></pre>
<p>Path a la carpeta pública de &#8220;uploads&#8221;:</p>
<pre>/path/to/project/[PROJECT_NAME]/web/uploads</pre>
<h3>Application Information</h3>
<pre><strong>sf_app</strong></pre>
<p>El nombre de la aplicación en la que está el archivo, como por ejemplo &#8220;frontend&#8221; o &#8220;backend&#8221;.</p>
<pre><strong>sf_environment</strong></pre>
<p>Entorno de desarrollo actual como por ejemplo &#8220;dev&#8221;.</p>
<pre><strong>sf_debug</strong></pre>
<p>Devuelve el estado actual del modo debug. Puede estar activado &#8220;1&#8243; o desactivado &#8220;0&#8243;.</p>
<h3>Application Structure and Layout</h3>
<pre><strong>sf_app_dir</strong></pre>
<p>Path a la carpeta de la aplicación actual:</p>
<pre>/path/to/project/[PROJECT_NAME]/apps/[APP_NAME]</pre>
<pre><strong>sf_app_config_dir</strong></pre>
<p>Path a la carpeta &#8220;config&#8221; de la aplicación actual:</p>
<pre>/path/to/project/[PROJECT_NAME]/apps/[APP_NAME]/config</pre>
<pre><strong>sf_app_lib_dir</strong></pre>
<p>Path a la carpeta &#8220;lib&#8221; de la aplicación actual:</p>
<pre>/path/to/project/[PROJECT_NAME]/apps/[APP_NAME]/lib</pre>
<pre><strong>sf_app_module_dir</strong></pre>
<p>Path a la carpeta &#8220;modules&#8221; de la aplicación actual:</p>
<pre>/path/to/project/[PROJECT_NAME]/apps/[APP_NAME]/modules</pre>
<pre><strong>sf_app_template_dir</strong></pre>
<p>Path a la carpeta &#8220;templates&#8221; de la aplicación actual:</p>
<pre>/path/to/project/[PROJECT_NAME]/apps/[APP_NAME]/templates</pre>
<pre><strong>sf_app_i18n_dir</strong></pre>
<p>Path a la carpeta &#8220;i18n&#8221; de la aplicación actual:</p>
<pre>/path/to/project/[PROJECT_NAME]/apps/[APP_NAME]/i18n</pre>
<h3>Cache Structure and Layout</h3>
<pre><strong>sf_app_base_cache_dir</strong></pre>
<p>Path a la carpeta de la aplicación actual dentro de la caché.</p>
<pre>/path/to/project/[PROJECT_NAME]/cache/[APP_NAME]</pre>
<pre><strong>sf_app_cache_dir</strong></pre>
<p>Path a la carpeta de la aplicación actual en el entorno de desarrollo actual dentro de la caché.</p>
<pre>/path/to/project/[PROJECT_NAME]/cache/[APP_NAME]/dev</pre>
<pre><strong>sf_template_cache_dir</strong></pre>
<p>Path a la carpeta &#8220;template&#8221; de la aplicación actual en el entorno de desarrollo actual dentro de la caché.</p>
<pre>/path/to/project/[PROJECT_NAME]/cache/[APP_NAME]/dev/template</pre>
<pre><strong>sf_i18n_cache_dir</strong></pre>
<p>Path a la carpeta &#8220;i18n&#8221; de la aplicación actual en el entorno de desarrollo actual dentro de la caché.</p>
<pre>/path/to/project/[PROJECT_NAME]/cache/[APP_NAME]/dev/i18n</pre>
<pre><strong>sf_config_cache_dir</strong></pre>
<p>Path a la carpeta &#8220;config&#8221; de la aplicación actual en el entorno de desarrollo actual dentro de la caché.</p>
<pre>/path/to/project/[PROJECT_NAME]/cache/[APP_NAME]/dev/config</pre>
<pre><strong>sf_test_cache_dir</strong></pre>
<p>Path a la carpeta &#8220;test&#8221; de la aplicación actual en el entorno de desarrollo actual dentro de la caché.</p>
<pre>/path/to/project/[PROJECT_NAME]/cache/[APP_NAME]/dev/test</pre>
<pre><strong>sf_module_cache_dir</strong></pre>
<p>Path a la carpeta &#8220;modules&#8221; de la aplicación actual en el entorno de desarrollo actual dentro de la caché.</p>
<pre>/path/to/project/[PROJECT_NAME]/cache/[APP_NAME]/dev/modules</pre>
<h3>Application Settings</h3>
<pre><strong>sf_error_404_module</strong></pre>
<p style="padding-left: 30px;">Módulo que ha hecho saltar el error 404.</p>
<pre><strong>sf_error_404_action</strong></pre>
<p style="padding-left: 30px;">Acción que ha hecho saltar el error 404.</p>
<pre><strong>sf_logging_enabled</strong></pre>
<p style="padding-left: 30px;">Valor boleano que nos indica si el loggin de la web está activo &#8220;1&#8243; o no &#8220;0&#8243;.</p>
<pre><strong>sf_escaping_strategy</strong></pre>
<p style="padding-left: 30px;">Valor boleano que indica si la clase sfView está usando Escaping Strategy &#8220;1&#8243; o no &#8220;0&#8243;.</p>
<pre><strong>sf_no_script_name</strong></pre>
<p style="padding-left: 30px;">Valor boleano que indica si la aplicación requiere nombre de script.</p>
<pre><strong>sf_csrf_secret</strong></pre>
<p style="padding-left: 30px;">La clave CSRF secreta configurada en la aplicación.</p>
<h3>También:</h3>
<p>Se puede acceder a la información del actual contexto con las siguientes funciones:</p>
<pre><strong>sfContext::getInstance()-&gt;getActionName();</strong></pre>
<p>Devuelve el nombre de la acción actual. También puede llamarse desde los templates con  $this-&gt;getActionName().</p>
<pre><strong>sfContext::getInstance()-&gt;getModuleName();</strong></pre>
<p>Nombre del módulo actual. También puede llamarse desde los templates con $this-&gt;getModuleName().</p>
<pre><strong>sfContext::getInstance()-&gt;getModuleDirectory();</strong></pre>
<p>Path al directorio del módulo actual:</p>
<pre>/path/to/project/[PROJECT_NAME]/apps/[APP_NAME]/modules/[MODULE_NAME]</pre>
<!-- google_ad_section_end -->]]></content:encoded>
			<wfw:commentRss>http://www.tecnoretales.com/programacion/la-clase-sfconfig-de-symfony/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cómo usar sfWidgetFormJQueryDate de sfFormExtraPlugin?</title>
		<link>http://www.tecnoretales.com/programacion/como-usar-sfwidgetformjquerydate-de-sfformextraplugin/</link>
		<comments>http://www.tecnoretales.com/programacion/como-usar-sfwidgetformjquerydate-de-sfformextraplugin/#comments</comments>
		<pubDate>Wed, 22 Jul 2009 20:43:32 +0000</pubDate>
		<dc:creator>Manel Pérez Mata</dc:creator>
				<category><![CDATA[Frameworks]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://www.tecnoretales.com/?p=552</guid>
		<description><![CDATA[sfFormExtraPlugin es un excelente plugin que mantienen los desarrolladores de Symfony con un montón de características adicionales que te ayudarán a construir formularios más completos.
¿Qué podemos encontrar en este plugin?
Són varias las utilidades que nos ofrece, desde la creación de campos captcha para evitar el spam hasta campos de texto autocompletables en función de lo [...]]]></description>
			<content:encoded><![CDATA[<!-- google_ad_section_start --><p>sfFormExtraPlugin es un excelente plugin que mantienen los desarrolladores de Symfony con un montón de características adicionales que te ayudarán a construir formularios más completos.</p>
<p><strong>¿Qué podemos encontrar en este plugin?</strong></p>
<p>Són varias las utilidades que nos ofrece, desde la creación de campos captcha para evitar el spam hasta campos de texto autocompletables en función de lo que vayamos escribiendo. Aquí os dejo una lista con sus posibilidades:</p>
<ol>
<li>ReCaptcha widget y validador</li>
<li>Editor HTML WYSIWYG para campos de texto</li>
<li>Selector de fechas tipo calendario</li>
<li>Selectores de idioma</li>
<li>Widget de listas dobles</li>
<li>Widget de autocompletado en campos de texto</li>
</ol>
<p><strong>¿Cómo instalar y usar sfWidgetFormJQueryDate?</strong></p>
<p>sfWidgetFormJQueryDate nos creará un selector de fechas con unas configuraciones mínimas para facilitar la tarea de rellenar los campos date en nuestros formularios. En la siguiente imágen, puedes ver el resultado de su correcta implementación:</p>
<p><img class="aligncenter size-full wp-image-553" title="sfwidgetformjquerydate" src="http://www.tecnoretales.com/wp-content/uploads/2009/07/sfwidgetformjquerydate.jpg" alt="sfwidgetformjquerydate" width="619" height="288" /><br />
<span id="more-552"></span><br />
A pesar de que este plugin está muy extendido, es muy poca la información que se puede encontrar sobre como instalarlo y usarlo correctamente. Espero que esta pequeña guía os sea de utilidad.</p>
<ol>
<li><strong>Instalar</strong> el plugin:<br />
<code>symfony plugin:install sfFormExtraPlugin</code></li>
<li>Una vez instalado, también necesitaremos <strong>descargar las librerías</strong> <a title="jQuery UI" href="http://jqueryui.com/download" target="_blank">jQuery UI</a> de la web oficial.</li>
<li>Ahora debemos <strong>configurar</strong> convenientemente nuestra aplicación para que use estas librerías javascript. Abre el zip descargado y mueve los archivos <em>jquery-1.3.2.min.js</em> y <em>jquery-ui-1.7.2.custom.min.js</em> a tu carpeta <em>/path/to/project/web/js/</em>Edita el archivo <em>/path/to/project/apps/[app]/config/view.yml</em> y añade esta información:<br />
<code>javascripts:    [jquery-1.3.2.min.js, jquery-ui-1.7.2.custom.min.js]</code></li>
<li>El siguiente paso será <strong>configurar los CSS</strong> de la librería jQuery UI. Añadimos  la siguiente información al archivo view.yml recién editado:<br />
<code>stylesheets:    [main.css, ui-lightness/jquery-ui-1.7.2.custom.css]</code></li>
<li>Configurar nuestro formulario para que utilice el widget:
<pre class="brush: php;">class myForm extends sfForm {
  public function configure()
  {
    $this-&gt;setWidgets(array(
      'from_date'    =&gt; new sfWidgetFormJQueryDate(array(
      'image'=&gt; '/images/icons/calendar_view_month.gif',
      'format' =&gt; '%day%/%month%/%year%')
    ),
      //...other widgets
    ));

    $this-&gt;widgetSchema-&gt;setLabels(array(
  		'from_date'    =&gt; 'From Date',
                //...other labels
    ));
  }
}</pre>
</li>
<li>Por último, lo prepararemos para usar en el action:
<pre class="brush: php;">  public function executeSearch(sfWebRequest $request){
    $this-&gt;form = new myForm();
    return sfView::SUCCESS;
  }</pre>
<p>y renderizaremos en la vista:</p>
<pre class="brush: php;">....
echo $form['from_date']-&gt;renderLabel().&quot;:&quot;.$form['from_date'];
....</pre>
</li>
</ol>
<p style="text-align: right;">Vía | <a href="http://symfonynerds.com/blog/?p=213" target="_blank">Symfonynerds.com</a></p>
<!-- google_ad_section_end -->]]></content:encoded>
			<wfw:commentRss>http://www.tecnoretales.com/programacion/como-usar-sfwidgetformjquerydate-de-sfformextraplugin/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Crear una relación many-to-many con Doctrine</title>
		<link>http://www.tecnoretales.com/programacion/crear-una-relacion-many-to-many-con-doctrine/</link>
		<comments>http://www.tecnoretales.com/programacion/crear-una-relacion-many-to-many-con-doctrine/#comments</comments>
		<pubDate>Tue, 14 Jul 2009 06:10:17 +0000</pubDate>
		<dc:creator>Manel Pérez Mata</dc:creator>
				<category><![CDATA[Frameworks]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[ORM]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://www.tecnoretales.com/?p=538</guid>
		<description><![CDATA[Vamos a ver como informar al magnífico ORM Doctrine de que debe tratar un par de tablas con una relación many-to-many utilizando una tabla intermedia.
Supongamos que tenemos una talba de jugadores de fútbol y una tabla de equipos. Un equipo estará compuesto por varios jugadores y a su vez, un jugador puede estar relacionado con [...]]]></description>
			<content:encoded><![CDATA[<!-- google_ad_section_start --><p>Vamos a ver como informar al magnífico <a title="Qué es Doctrine ORM?" href="http://www.tecnoretales.com/programacion/que-es-doctrine-orm/">ORM Doctrine</a> de que debe tratar un par de tablas con una <strong>relación many-to-many</strong> utilizando una tabla intermedia.</p>
<p>Supongamos que tenemos una talba de jugadores de fútbol y una tabla de equipos. Un equipo estará compuesto por varios jugadores y a su vez, un jugador puede estar relacionado con varios equipos (el actual, más los equipos por los que ha pasado en su vida deportiva).</p>
<p>Para este ejemplo necesitaremos tres tablas: Team, Player  y una relacional TeamPlayer. <span id="more-538"></span>El schema.yml de este escenario sería:</p>
<pre class="brush: plain;"># Player table
Player:
  tableName: player
  columns:
    id:
      type: integer(4)
      unsigned: 1
      primary: true
      autoincrement: true
    first_name: string(255)
    last_name: string(255)
    weight: float(2147483647)
    height: float(2147483647)
  relations:
    Team:
      &lt;strong&gt;class&lt;/strong&gt;: Team
      &lt;strong&gt;local&lt;/strong&gt;: player_id
      &lt;strong&gt;foreign&lt;/strong&gt;: team_id
      &lt;strong&gt;refClass&lt;/strong&gt;: TeamPlayer

#Team table
tableName: team
  columns:
    id:
      type: integer(4)
      unsigned: 1
      primary: true
      autoincrement: true
    name: string(255)
  relations:
    Player:
      &lt;strong&gt;class&lt;/strong&gt;: Player
      &lt;strong&gt;local&lt;/strong&gt;: team_id
      &lt;strong&gt;foreign&lt;/strong&gt;: player_id
      &lt;strong&gt;refClass&lt;/strong&gt;: TeamPlayer

#TeamPlayer table
TeamPlayer:
  tableName: team_player
  columns:
    team_id:
      type: integer(4)
      unsigned: 1
      primary: true
    player_id:
      type: integer(4)
      unsigned: 1
      primary: true</pre>
<p>Los puntos importantes están en las relaciones de las tablas Team y Player, donde indicaremos los campos:</p>
<ul>
<li><strong><span style="text-decoration: underline;">class</span>:</strong> La clase encargada de manejar el objeto relacionado.</li>
<li><strong><span style="text-decoration: underline;">local</span>:</strong> El nombre del campo que hace de vínculo entre la tabla en la que estoy y la tabla relacional TeamPlayer</li>
<li><strong><span style="text-decoration: underline;">foreign</span>:</strong> El nombre del campo que hace de vínculo entre la tabla relacionada y la tabla relacional TeamPlayer</li>
<li><strong><span style="text-decoration: underline;">refClass</span>:</strong> Nombre del objeto encargado de realizar la relación</li>
</ul>
<p>Siguiendo estos pasos podremos acceder a todos los equipos de un jugador y a todos los jugadores de un equipo sin ningún problema.</p>
<!-- google_ad_section_end -->]]></content:encoded>
			<wfw:commentRss>http://www.tecnoretales.com/programacion/crear-una-relacion-many-to-many-con-doctrine/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	<!-- google ad injected by adsense-optimizer http://www.adsenseoptimizer.de -->
			<div  style="padding:7px; display: block; margin-left: auto; margin-right: auto; text-align: center;"><!-- Ad number: 3 --><script type="text/javascript"><!--
    	 
    	google_ad_client = "pub-7180773421652966"; google_alternate_color = "FFFFFF";
		google_ad_width = 468; google_ad_height = 60;
		google_ad_format = "468x60_as"; google_ad_type = "text";
		google_ad_channel =""; google_color_border = "FE8B00";
		google_color_link = "FE8B00"; google_color_bg = "FFFFFF";
		google_color_text = "000000"; google_color_url = "D9D9D9";
		google_ui_features = "rc:6"; //--></script>
		<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script></div>	<item>
		<title>Configurar Doctrine en Symfony</title>
		<link>http://www.tecnoretales.com/bases-de-datos/configurar-doctrine-en-symfony/</link>
		<comments>http://www.tecnoretales.com/bases-de-datos/configurar-doctrine-en-symfony/#comments</comments>
		<pubDate>Tue, 07 Jul 2009 14:23:27 +0000</pubDate>
		<dc:creator>Manel Pérez Mata</dc:creator>
				<category><![CDATA[Bases de datos]]></category>
		<category><![CDATA[Frameworks]]></category>
		<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[ORM]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://www.tecnoretales.com/?p=496</guid>
		<description><![CDATA[ Symfony integra Propel ORM por defecto, sin embargo, Doctrine está ganando puntos sobre su rival.
La principal ventaja de cada uno de ellos es:
Propel: Está completamente integrado con Symfony y decenas de plugins sólo funcionan para Propel.
Doctrine: Tiene muy buen rendimiento en ejecución y una forma muy concisa al escribir consultas complejas.
Si te has decidido [...]]]></description>
			<content:encoded><![CDATA[<!-- google_ad_section_start --><p><img class="alignleft size-full wp-image-497" src="http://www.tecnoretales.com/wp-content/uploads/2009/07/doctrine.gif" alt="Doctrine Logo" width="191" height="53" /> Symfony integra Propel ORM por defecto, sin embargo, Doctrine está ganando puntos sobre su rival.</p>
<p>La principal ventaja de cada uno de ellos es:</p>
<p><strong>Propel:</strong> Está completamente integrado con Symfony y decenas de plugins sólo funcionan para Propel.</p>
<p><strong>Doctrine:</strong> Tiene muy buen rendimiento en ejecución y una forma muy concisa al escribir consultas complejas.</p>
<p>Si te has decidido a utilizar Doctrine en lugar de Propel y no sabes como integrarlo con Symfony, aquí te dejo los pasos para activarlo.<span id="more-496"></span></p>
<ol>
<li>Lo primero que deberemos hacer es habilitar <em>sfDoctrinePlugin</em> y deshabilitar <em>sfPropelPlugin</em>, esto lo haremos editando el archivo <em>config/ProjectConfiguration.class.php </em>:
<pre class="brush: php;">
public function setup()
{
  $this-&gt;enablePlugins(array('sfDoctrinePlugin'));
  $this-&gt;disablePlugins(array('sfPropelPlugin'));
}
</pre>
<p>o si lo prefieres, puedes habilitar todos los plugins por defecto excepto los que no te interesen:</p>
<pre class="brush: php;">
public function setup()
{
  $this-&gt;enableAllPluginsExcept(array('sfPropelPlugin'));
}
</pre>
</li>
<li>Activado Doctrine, borraremos la caché para asegurarnos que se cargan nuestros cambios:<br />
<code>symfony cc</code></li>
<li>Crearemos una carpeta <em>doctrine</em> dentro de <em>config</em> que contendrá nuestro archivo <em>schema.yml</em> y listo, ya tenemos a Symfony funcionando con Doctrine</li>
<li>Ahora sólo queda abrir el archivo <em>config/databases.yml</em> y cambiar &#8220;<em>propel</em>&#8221; por &#8220;<em>doctrine</em>&#8221; (respetando mayúsculas y minúsculas) y eliminar la linea &#8220;<em>classname:  PropelPDO</em>&#8220;.</li>
</ol>
<p>Recordemos que a partir de ahora, deberemos utilizar la sintaxis Doctrine, tanto en nuestra definición del schema como en el modelo de nuestra aplicación. Si son tus primeros pasos con Doctrine, puedes ver su documentación original <a title="Doctrine Tutorial" href="http://www.doctrine-project.org/documentation/manual/1_1/en/introduction" target="_blank">aquí</a>.</p>
<!-- google_ad_section_end -->]]></content:encoded>
			<wfw:commentRss>http://www.tecnoretales.com/bases-de-datos/configurar-doctrine-en-symfony/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Qué es Doctrine ORM?</title>
		<link>http://www.tecnoretales.com/programacion/que-es-doctrine-orm/</link>
		<comments>http://www.tecnoretales.com/programacion/que-es-doctrine-orm/#comments</comments>
		<pubDate>Fri, 03 Jul 2009 09:48:54 +0000</pubDate>
		<dc:creator>Manel Pérez Mata</dc:creator>
				<category><![CDATA[Bases de datos]]></category>
		<category><![CDATA[Frameworks]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[ORM]]></category>

		<guid isPermaLink="false">http://www.tecnoretales.com/?p=487</guid>
		<description><![CDATA[Qué es un ORM?
Un ORM o (Object Relation Mapper) es una técnica de programación que nos permite convertir datos entre el sistema de tipos utilizado en un lenguaje de programación orientado a objetos y el utilizado en una base de datos relacional, es decir, las tablas de nuestra base de datos pasan a ser clases [...]]]></description>
			<content:encoded><![CDATA[<!-- google_ad_section_start --><p><strong>Qué es un ORM?</strong></p>
<p>Un ORM o (Object Relation Mapper) es una técnica de programación que nos permite convertir datos entre el sistema de tipos utilizado en un lenguaje de programación orientado a objetos y el utilizado en una base de datos relacional, es decir, las tablas de nuestra base de datos pasan a ser clases y los registros objetos que podemos manejar con facilidad.</p>
<p><img class="aligncenter size-full wp-image-489" title="fig02" src="http://www.tecnoretales.com/wp-content/uploads/2009/07/fig02.jpg" alt="fig02" width="362" height="438" /></p>
<p><span id="more-487"></span>Utilizar un ORM tiene una serie de ventajas que nos facilitan enormemente tareas comúnes y de mantenimiento:</p>
<ol>
<li><strong>Reutilización:</strong> La principal ventaja que aporta un ORM es la reutilización permitiendo llamar a los métodos de un objeto de datos desde distintas partes de la aplicación e incluso desde diferentes aplicaciones.</li>
<li><strong>Encapsulación:</strong> La capa ORM encapsula la lógica de los datos pudiendo hacer cambios que afectan a toda la aplicación únicamente modificando una función.</li>
<li><strong>Portabilidad:</strong> Utilizar una capa de abstracción nos permite cambiar en mitad de un proyecto de una base de datos MySQL a una Oracle sin ningún tipo de complicación. Esto es debido a que no utilizamos una sintaxis MySQL, Oracle o SQLite para acceder a nuestro modelo, sino una sintaxis propia del ORM utilizado que es capaz de traducir a diferentes tipos de bases de datos.</li>
<li><strong>Seguridad:</strong> Los ORM suelen implementar mecanísmos de seguridad que protegen nuestra aplicación de los ataques más comúnes como SQL Injections.</li>
<li><strong>Mantenimiento del código:</strong> Gracias a la correcta ordenación de la capa de datos, modificar y mantener nuestro código es una tarea sencilla.</li>
</ol>
<p><strong>Qué es Doctrine?</strong></p>
<p><img class="alignleft size-full wp-image-488" title="doctrine-logo" src="http://www.tecnoretales.com/wp-content/uploads/2009/07/doctrine-logo.png" alt="doctrine-logo" width="119" height="96" />Según la <a title="Doctrine ORM" href="http://www.doctrine-project.org/" target="_blank">documentación oficial</a>, Doctrine es un <strong>ORM para PHP</strong> 5.2.3 y posterior. Además de todas las ventajas que conlleva un ORM, uno de sus puntos fuertes es su lenguaje <strong>DQL</strong> (Doctrine Query Language) <strong>inspirado en el HQL de Hibernate</strong>.</p>
<p>Cuando trabajamos con Doctrine, necesitamos informar a su motor interno de cual es el modelo de nuestra aplicación, para ello podemos hacer <strong>ingeniería inversa</strong> de nuestra base de datos existente, o si empezamos la aplicación desde 0, crear el modelo en la sintaxis específica que nos propone Doctrine y luego generar toda la base de datos.</p>
<p>Para crear el modelo, doctrine nos da dos alternativas, hacer una clase por tabla e indicarle mediante PHP el tipo de datos que almacenaremos en él, un ejemplo:</p>
<pre class="brush: php;">// models/generated/BaseUser.php

class User extends BaseUser
{
    public function setTableDefinition()
    {
        $this-&gt;hasColumn('username', 'string', 255, array('default' =&gt; 'default username'));
        $this-&gt;hasColumn('name', 'string', 255, array('default' =&gt; 'default name'));
        $this-&gt;hasColumn('age', 'integer', 4, array('unsigned' =&gt; true));
        // ...
    }

    // ...
}</pre>
<p>O crear un esquema en <a title="Yaml" href="http://es.wikipedia.org/wiki/YAML" target="_blank">formato YAML</a> (<em>schema.yml</em>) similar a XML, pero bastante más legible. El equivalente al ejemplo anterior en YAML sería:</p>
<pre class="brush: plain;"># schema.yml

# ...
User:
# ...
  columns:
    username:
      type: string(255)
      default: default username
    name:
      type: string(255)
      default: default name
    age:
      type: integer(4)
      unsigned: true
    # ...</pre>
<p>Además de definir los campos de cada tabla, también le indicamos las relaciones que tienen con las otras tablas y su tipo (many-to-many, one-to-many, one-to-one&#8230;), lo que deja perfectamente estructurada nuestro modelo de datos y su manera de acceder a los valores.</p>
<p>Más adelante seguiré escribiendo sobre las ventajas de Doctrine y añadiendo ejemplos que considere interesantes y/o útiles.</p>
<!-- google_ad_section_end -->]]></content:encoded>
			<wfw:commentRss>http://www.tecnoretales.com/programacion/que-es-doctrine-orm/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Implementar FullCalendar en Symfony</title>
		<link>http://www.tecnoretales.com/programacion/implementar-fullcalendar-en-symfony/</link>
		<comments>http://www.tecnoretales.com/programacion/implementar-fullcalendar-en-symfony/#comments</comments>
		<pubDate>Fri, 12 Jun 2009 06:20:05 +0000</pubDate>
		<dc:creator>Manel Pérez Mata</dc:creator>
				<category><![CDATA[Frameworks]]></category>
		<category><![CDATA[Programación]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://www.tecnoretales.com/?p=401</guid>
		<description><![CDATA[FullCalendar es un plugin jQuery que nos permite implementar de manera sencilla un calendario con una interfaz visual excelente y muy fácil de personalizar. Además, podemos hacer Drag&#38;Drop (arrastrar y soltar) de los eventos agendados para pasarlos de un día a otro.
Hoy vamos a montar en symfony un módulo que nos mostrará un calendario con [...]]]></description>
			<content:encoded><![CDATA[<!-- google_ad_section_start --><p><a title="FullCalendar" href="http://arshaw.com/fullcalendar/" target="_blank">FullCalendar</a> es un plugin jQuery que nos permite implementar de manera sencilla un calendario con una interfaz visual excelente y muy fácil de personalizar. Además, podemos hacer Drag&amp;Drop (arrastrar y soltar) de los eventos agendados para pasarlos de un día a otro.</p>
<p>Hoy vamos a montar en symfony un módulo que nos mostrará un calendario con los eventos almacenados en nuestra base de datos. La parte de administración no la desarrollaré, pero con las completas herramientas que nos ofrece symfony, nos será muy fácil montarlo (si estás dando tus primeros pasos con Symfony, te recomiendo realizar este <a title="Tutorial Symfony" href="http://www.symfony-project.org/jobeet/1_2/Doctrine/es/" target="_blank">tutorial</a> donde podrás ver paso a paso como se implementa un projecto con Symfony).</p>
<p><img class="aligncenter size-full wp-image-404" title="FullCalendar" src="http://www.tecnoretales.com/wp-content/uploads/2009/06/fullcalendar.png" alt="FullCalendar" width="600" height="379" /></p>
<h3><span id="more-401"></span>Generando y configurando el proyecto</h3>
<p>Empezaremos desde el principio, creando el proyecto, la aplicación frontend y el módulo calendar:</p>
<pre>symfony generate:project calendar
symfony generate:app frontend
symfony generate:module frontend calendar</pre>
<p>Ahora conectamos nuestro proyecto con la base de datos modificando el archivo <em>/path/to/project/config/databases.yml</em></p>
<pre class="brush: plain;">all:
  propel:
    class:        sfPropelDatabase
    param:
      classname:  PropelPDO
      dsn:        mysql:dbname=&lt;strong&gt;[DB-NAME]&lt;/strong&gt;;host=localhost
      username:   &lt;strong&gt;[DB-USER]&lt;/strong&gt;
      password:   &lt;strong&gt;[DB-PASS]&lt;/strong&gt;
      encoding:   utf8
      persistent: true
      pooling:    true</pre>
<p>Nuestro siguiente paso será añadir la estructura de base de datos al archivo <em>/path/to/project/config/schema.yml</em></p>
<pre class="brush: plain;">propel:
  cal:
    id: ~
    description: {type:varchar(50), required: true }
    category: {type: integer, foreignTable: cal_category, foreignReference: id, required: true}
    details: {type:varchar(255), required: true }
    dstart: {type: date, required: true }
    dend: {type: date, required: true }
    created_at: ~
    updated_at: ~
    _indexes:
      intra_cal_I_1: [dstart]
      intra_cal_I_1: [dend]

  cal_category:
    id: ~
    category: {type:varchar(50), required: true, index: unique}
    created_at: ~
    updated_at: ~</pre>
<p>y ahora, desde línea de comandos, indicaremos a symfony que genere la base de datos y el modelo de datos, para ello, ejecutamos:</p>
<pre>symfony propel:build-all</pre>
<p>Con estos pasos ya tenemos preparado nuestro proyecto para integrar FullCalendar&#8230; manos a la obra!</p>
<h3>Integrando FullCalendar</h3>
<p>El primer paso será bajarnos <a title="Download jQuery" href="http://docs.jquery.com/Downloading_jQuery" target="_blank">jQuery</a> y <a title="Download FullCalendar" href="http://arshaw.com/fullcalendar/download/" target="_blank">FullCalendar</a> de las páginas oficiales. Después guardamos los js <strong>jquery.min.js</strong>, <strong>fullcalendar.min.js</strong>, <strong>ui.draggable.js</strong> y <strong>ui.core.js</strong> en la carpeta <em>/path/to/project/web/js</em> y el css <strong>fullcalendar.css</strong> en <em>/path/to/project/web/css</em>.</p>
<p>Suele ser buena práctica definir las rutas antes de empezar a programar.  Dejaremos la ruta por defecto para mostrar el calendario, pero modificaremos la que nos muestra los detalles para indicarle que debe usar la clase sfPropelRoute que nos permitirá obtener el objeto job sin necesidad de generar la consulta SQL. Abrimos el archivo <em>/path/to/project/apps/frontend/config/routing.yml</em> y le añadimos:</p>
<pre class="brush: plain;">cal_show_event:
  url:   /:module/:action/id/:id
  class:   sfPropelRoute
  options: { model: Cal, type: object }
  param:   { module: calendar, action: show }</pre>
<p>El siguiente paso será implementar los eventos del mes actual hacia adelante, añadiendo la siguiente función al archivo <em>/path/to/project/lib/model/CalPeer.php</em></p>
<pre class="brush: php;">  static public function getCalEvents(){
    // crea el inicio de mes
    $IniMes = date('d-m-Y',mktime(0,0,0,date('m'),1,date('Y')));
    $criteria = new Criteria();
    $criteria-&gt;add(self::DSTART, $IniMes, Criteria::GREATER_EQUAL);
    return self::doSelect($criteria);
  }</pre>
<p>En el index de nuestro módulo <em>/path/to/project/apps/frontend/modules/calendar/actions/actions.class.php</em> llamámos a esta función:</p>
<pre class="brush: php;">  public function executeIndex(sfWebRequest $request)
  {
    $this-&gt;cal_list = CalPeer::getCalEvents();
  }
  public function executeShow(sfWebRequest $request)
  {
    $this-&gt;cal = $this-&gt;getRoute()-&gt;getObject();
  }</pre>
<p>Ahora es el momento de crear la vista  <em>/path/to/project/apps/frontend/modules/calendar/templates/indexSuccess.php</em></p>
<pre class="brush: php;">&lt;?php use_stylesheet('fullcalendar.css') ?&gt;
&lt;script type='text/javascript'&gt;

$(document).ready(function() {

var d = new Date();
var y = d.getFullYear();
var m = d.getMonth();

$('#calendar').fullCalendar({
draggable: true,
events: [
&lt;?php $total = count($intra_cal_list); $i=0; ?&gt;
&lt;?php foreach ($cal_list as $intra_cal): ?&gt;
{
&lt;?php $i++; ?&gt;
id: &lt;?php echo $intra_cal-&gt;getId() ?&gt;,
title: &quot;&lt;?php echo $intra_cal-&gt;getDescription() ?&gt;&quot;,
&lt;?php
$fecha = strtotime($intra_cal-&gt;getDstart());
$anno = date(&quot;Y&quot;, $fecha);
$mes = date(&quot;m&quot;, $fecha);
$mes--;
$dia = date(&quot;d&quot;, $fecha);
?&gt;
start: &lt;?php echo &quot;new Date(&quot;.$anno.&quot;, &quot;.$mes.&quot;, &quot;.$dia.&quot;)&quot;; ?&gt;,
&lt;?php
$fecha = strtotime($intra_cal-&gt;getDend());
$anno = date(&quot;Y&quot;, $fecha); $mes = date(&quot;m&quot;, $fecha);
$mes--;
$dia = date(&quot;d&quot;, $fecha);
?&gt;
end: &lt;?php echo &quot;new Date(&quot;.$anno.&quot;, &quot;.$mes.&quot;, &quot;.$dia.&quot;)&quot;; ?&gt;,
url: &quot;&lt;?php echo url_for('cal/show?id='.$intra_cal-&gt;getId()) ?&gt;&quot;
}&lt;?php if ($i != $total) echo &quot;,&quot; ?&gt;
&lt;?php endforeach; ?&gt;
]
});

});

&lt;/script&gt;

&lt;div id='calendar'&gt;&lt;/div&gt;</pre>
<p>y la vista que nos mostrará el detalle de un evento <em>/path/to/project/apps/frontend/modules/calendar/templates/showSuccess.php</em></p>
<pre class="brush: php;">&lt;h1&gt;&lt;?php echo $cal-&gt;getDescription()?&gt;&lt;/h1&gt;
&lt;?php echo $cal-&gt;getDetails() ?&gt;</pre>
<p>Por último, añadimos las siguientes líneas al layout <em>/path/to/project/apps/frontend/templates/layout.php</em></p>
<pre class="brush: php;">&lt;?php use_javascript('jquery.min.js') ?&gt;
&lt;?php use_javascript('fullcalendar.min.js') ?&gt;
&lt;?php use_javascript('ui.core.js') ?&gt;
&lt;?php use_javascript('ui.draggable.js') ?&gt;</pre>
<p>Hecho esto, si accedemos a nuestra aplicación desde el navegador http://localhost/web/calendar/index veremso nuestro calendario funcionando.</p>
<!-- google_ad_section_end -->]]></content:encoded>
			<wfw:commentRss>http://www.tecnoretales.com/programacion/implementar-fullcalendar-en-symfony/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
	</channel>
</rss>

