<?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; Symfony</title>
	<atom:link href="http://www.tecnoretales.com/tag/symfony/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>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>
		<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>
	<!-- 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>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>
		<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>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>
	<!-- 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>Mi primer proyecto con Symfony 1.2.7 (parte II)</title>
		<link>http://www.tecnoretales.com/programacion/mi-primer-proyecto-con-symfony-127-parte-ii/</link>
		<comments>http://www.tecnoretales.com/programacion/mi-primer-proyecto-con-symfony-127-parte-ii/#comments</comments>
		<pubDate>Fri, 22 May 2009 15:00:22 +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=317</guid>
		<description><![CDATA[Esta artículo es la segunda parte de mis primeros pasos con Symfony, puedes ver la primer parte de como crear un proyecto con Symfony, donde se describe paso a paso como diseñar y generar el proyecto, crear las aplicaciones y los módulos y conectar nuestro proyecto con la base de datos.
En esta segunda parte, vamos [...]]]></description>
			<content:encoded><![CDATA[<!-- google_ad_section_start --><p><img class="alignleft size-full wp-image-319" title="Symfony Logo" src="http://www.tecnoretales.com/wp-content/uploads/2009/05/symfony-logo.png" alt="Symfony Logo" width="38" height="39" />Esta artículo es la segunda parte de mis primeros pasos con Symfony, puedes ver la primer parte de <a title="Crear un proyecto con Symfony" href="http://www.tecnoretales.com/programacion/mi-primer-proyecto-con-symfony-127-parte-i/">como crear un proyecto con Symfony</a>, donde se describe paso a paso como diseñar y generar el proyecto, crear las aplicaciones y los módulos y conectar nuestro proyecto con la base de datos.</p>
<p>En esta segunda parte, vamos a dar forma a la parte pública y privada,  hacer uso del scaffolding para generar las acciones comunes CRUD (Create, Read, Update, Delete) o como tunear las URLs para <a title="SEO" href="http://www.tecnoretales.com/categoria/internet/seo-internet/">conseguir un mejor posicionamiento</a>.<span id="more-317"></span></p>
<h3>Dando forma a la parte privada backend</h3>
<p>Generalmente, la parte de administración de cualquier web suele ser una tarea bastante repetitiva y poco agradable de realizar. Para simplificarlo, Symfony dispone de un modulo de <a title="Scaffolding en Symfony" href="http://www.librosweb.es/symfony_1_0/capitulo14/scaffolding.html" target="_blank">Scaffolding</a> que nos facilitará enormemente la tarea, creando el código necesario para hacer las operaciones básicas de creación, lectura, modificación y borrado de registros en base de datos.</p>
<p>Vamos a crear la parte de administración de nuestros dos módulos (posts y comments) con el comando propel:init-admin    donde clase es la clase PHP que se encarga de representar la tabla de datos:</p>
<pre>symfony propel:init-admin backend post Post
symfony propel:init-admin backend comment Comment</pre>
<p>Pues ya tenemos creada las operaciones CRUD de las dos tablas, si visitamos la url http://localhost/blog/post, veremos un listado (de momento vacío) y un botón para crear nuestro primer post. En esta imágen, podemos ver el resultado del listado de posts:</p>
<div id="attachment_330" class="wp-caption aligncenter" style="width: 470px"><img class="size-full wp-image-330" title="List Post interface" src="http://www.tecnoretales.com/wp-content/uploads/2009/05/f1405.png" alt="Interfaz de listado de posts" width="460" height="206" /><p class="wp-caption-text">Listado de posts</p></div>
<p>y en esta otra, el formulario de alta/modificación:</p>
<div id="attachment_329" class="wp-caption aligncenter" style="width: 425px"><img class="size-full wp-image-329" title="Listed posts" src="http://www.tecnoretales.com/wp-content/uploads/2009/05/f1406.png" alt="Interfaz de listado de Posts" width="415" height="304" /><p class="wp-caption-text">Edición de Posts</p></div>
<p>La parte de gestión de comentarios es idéntica a la de los artículos, salvo que en este caso, el formulario de creación del comentario también muestra la clave externa que hace referencia a los artículos. Para mostrar la clave externa, Symfony utiliza el método mágico de PHP llamado <em>__toString()</em>.</p>
<p>Si no se ha definido este método, se muestra directamente el valor numérico de id. Si se quiere mostrar el título del post en lugar de su id, tan sólo se debe definir el método mágico <em> __toString()</em> en la clase del modelo de los artículos (en el archivo <em>lib/model/Post.php</em>):</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">class</span> Post <span class="kw2">extends</span> BasePost</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw2">public</span> <span class="kw2">function</span> __toString<span class="br0">&#40;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> self::<span class="me2">getTitle</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>Si ahora queremos, añadir un buscador a nuestra página de resultados de comentarios, modificar las columnas que se muestras o el número de resultados por página, lo podemos hacer de una manera simple añadiendo información al archivo <em>generator.yml</em> del módulo de comentarios (/var/www/blog/apps/backend/modules/comment/config/generator.yml).</p>
<p>Añadiendo la siguiente información al archivo:</p>
<pre>generator:
  class:              sfPropelAdminGenerator
  param:
    model_class:      Comment
    theme:            default
    list:
      display:        [author, body]
      filters:        [post_id, author, body]
      max_per_page:   5</pre>
<p>Conseguimos modificar el número de resultados por página, las columnas mostradas y añadir una caja buscadora:</p>
<p style="text-align: center;">
<div id="attachment_333" class="wp-caption aligncenter" style="width: 676px"><img class="size-full wp-image-333" title="Symfony Comment Filtrado" src="http://www.tecnoretales.com/wp-content/uploads/2009/05/symfony-comment-filtered.gif" alt="Symfony Filtrado en comentarios" width="666" height="189" /><p class="wp-caption-text">Filtrado en lista de comentarios</p></div>
<p>Puedes ver todas las opciones de personalización que nos da el generador <a title="Configuración del generador" href="http://www.librosweb.es/symfony_1_2/capitulo14/configuracion_del_generador.html" target="_blank">aquí</a>.</p>
<p><strong>Nota!!</strong> Después de cualquier cambio en un archivo *.yml es necesario que eliminemos la caché de Symfony para ver los resultados por pantalla. Para ello, ejecutamos desde consola symfony cc.</p>
<h3>Dando forma a la parte pública frontend</h3>
<p>La parte pública, tiene un desarrollo más manual pero aprovecharemos las utilidades que Symfony pone a nuestra disposición para darle forma.</p>
<p>Creamos los modulos del frontend (post y comment) lanzando desde consola la instrucción:</p>
<pre>symfony generate:module frontend post
symfony generate:module frontend comment</pre>
<p>Si visitamso la dirección http://localhost/blog/post, veremos la página inicial de Symfony. Este módulo, debería mostrar, por ejemplo, un listado de los posts publicados actualmente y al acceder a uno de ellos, mostrar la página de la noticia.</p>
<p>Para crear las acciones de listado y muestra, modificaremos el archivo <em>/var/www/blog/apps/frontend/modules/post/actions/actions.class.php</em> y añadiremos los dos métodos que se encargarán de realizarlas:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">class</span> postActions <span class="kw2">extends</span> sfActions</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;<span class="coMULTI">/**</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp; * Executes index action</span></div>
</li>
<li class="li2">
<div class="de2"><span class="coMULTI">&nbsp; *</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp; * @param sfRequest $request A request object</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp; */</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw2">public</span> <span class="kw2">function</span> executeIndex<span class="br0">&#40;</span>sfWebRequest <span class="re0">$request</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="re0">$this</span>-&gt;<span class="me1">forward</span><span class="br0">&#40;</span><span class="st0">&#8216;post&#8217;</span>, <span class="st0">&#8216;list&#8217;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;<span class="coMULTI">/**</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp; * Executes list posts action</span></div>
</li>
<li class="li2">
<div class="de2"><span class="coMULTI">&nbsp; */</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw2">public</span> <span class="kw2">function</span> executeList<span class="br0">&#40;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li2">
<div class="de2">&nbsp;<span class="coMULTI">/**</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp; * Executes show post action</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp; */</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw2">public</span> <span class="kw2">function</span> executeShow<span class="br0">&#40;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>Ok, ya le hemos indicado al módulo que dispone de dos acciones más, listar y mostrar, además, le hemos indicado a la acción por defecto <em>&#8216;index&#8217;</em> que haga una redirección hacia la acción <em>&#8216;list&#8217;</em>, por lo tanto, si visitamos http://localhost/blog/post o http://localhost/blog/post/list obtendremos el mismo resultado.</p>
<p>Llegados a este punto, es interesante explicar como es capaz Symfony de llegar al módulo indicado, la acción correcta y como llama a los templates adecuados. Como habreis deducido, Symfony es capaz de rescatar el módulo y la acción a partir de la URL que escribimos en el navegador, así bien, la URL tiene un formato:</p>
<p>http://dominio.foo/<strong>&lt;modulo&gt;</strong>/<strong>&lt;accion&gt;</strong>/<strong>&lt;key_var_1&gt;</strong>/<strong>&lt;value_var_1&gt;</strong>/&#8230;</p>
<p>Más adelante, veremos que se pueden personalizar las URLs para hacerlas más atractivas a los buscadores, pero por el momento, seguiremos trabajando con los valores por defecto.</p>
<p>Symfony irá a buscar un template html en la carpeta <em>/var/www/blog/apps/frontend/modules/post/templates</em> con el nombre &lt;nombreAccion&gt;+&lt;ResultadoAccion&gt; (en este caso listSuccess.php), parseará las variables y devolverá el resultado por pantalla.</p>
<p>El siguiente paso, será indicar al controlador (post/actions/actions.class.php) que solicite al modelo los posts existentes en base de datos y que se los pase a la vista. El resultado en forma de código sería:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"> &nbsp;<span class="kw2">public</span> <span class="kw2">function</span> executeList<span class="br0">&#40;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$c</span> = <span class="kw2">new</span> Criteria<span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$posts</span> = PostPeer::<span class="me2">doSelect</span><span class="br0">&#40;</span><span class="re0">$c</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$this</span>-&gt;<span class="me1">posts</span> = <span class="re0">$posts</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p><strong>Nota!!</strong> Todo valor establecido en la variable this de una acción será asignado automáticamente a la vista con el mismo nombre. En este caso, podremos utilizar <em>$posts</em> en el template <em>listSuccess.php</em>.</p>
<p>Ahora vamos a dar forma al template html que muestra el listado de posts. Creamos el archivo listSuccess.php en la carpeta de templates e insertamos esta información:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&lt;?php use_helper(&#8217;Text&#8217;) ?&gt;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&lt;h1&gt;Mi Primer Proyecto con Symfony&lt;/h1&gt;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li2">
<div class="de2">&lt;?php foreach($posts as $post): ?&gt;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &lt;h2&gt;&lt;?php echo $post-&gt;getTitle() ?&gt;&lt;/h2&gt;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &lt;p&gt;&lt;?php echo truncate_text($post-&gt;getBody(), 200) ?&gt;&lt;/p&gt;
</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &lt;?php echo link_to(&#8217;Continuar leyendo&#8230;&#8217;, &#8216;post/show/?id=&#8217;.$post-&gt;getId()) ?&gt;
</div>
</li>
<li class="li1">
<div class="de1">&lt;?php endforeach; ?&gt;</div>
</li>
</ol>
</div>
<p>La primera línea se encarga de instanciar el helper Text, que nos permite usar la función truncate_text encargada de recortar el texto a 200 caracteres. También hacemos uso de link_to, disponible sin necesidad de instanciar ningún helper, encargada de crear un enlace con el texto &#8220;Continuarl leyendo&#8230;&#8221;  hacia la dirección indicada en el segundo parámetro.</p>
<p>Una vez tenemos la página de listado de posts, montaremos la que muestra la noticia. Añadiremos la siguiente información al método <em>executeShow</em> de la clase <em>actions.class.php</em> del módulo <em>post</em>:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">public</span> <span class="kw2">function</span> executeShow<span class="br0">&#40;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$id</span> = <span class="re0">$this</span>-&gt;<span class="me1">getRequestParameter</span><span class="br0">&#40;</span><span class="st0">&#8216;id&#8217;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$post</span> = PostPeer::<span class="me2">retrieveByPk</span><span class="br0">&#40;</span><span class="re0">$id</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$this</span>-&gt;<span class="me1">forward404Unless</span><span class="br0">&#40;</span><span class="re0">$post</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$this</span>-&gt;<span class="me1">post</span> = <span class="re0">$post</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>El código recoge el parámetro id pasado por GET y  solicita al modelo el post con el id recogido. Si no existe el post solicitado, mostramos un error 404, en caso contrario, mostraremos la página resultante. El template asociado a esta acción sería:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&lt;h1&gt;&lt;?php <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$post</span>-&gt;<span class="me1">getTitle</span><span class="br0">&#40;</span><span class="br0">&#41;</span> ?&gt;&lt;/h1&gt;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&lt;p&gt;&lt;?php <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$post</span>-&gt;<span class="me1">getExcerpt</span><span class="br0">&#40;</span><span class="br0">&#41;</span> ?&gt;&lt;/p&gt;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li2">
<div class="de2">&lt;p&gt;&lt;?php <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$post</span>-&gt;<span class="me1">getBody</span><span class="br0">&#40;</span><span class="br0">&#41;</span> ?&gt;&lt;/p&gt;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?php</span> <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> link_to<span class="br0">&#40;</span><span class="st0">&#8216;Volver&#8217;</span>, <span class="st0">&#8216;post/list&#8217;</span><span class="br0">&#41;</span> <span class="kw2">?&gt;</span></div>
</li>
</ol>
</div>
<p>y lo guardaremos con el nombre <em>showSuccess.php</em> en la carpeta de templates.</p>
<h3>Modificando la URL por defecto</h3>
<p>A peasr de que las URLs que compone Symfony por defecto son bastante semánticas, en este caso, sería interesante que, en lugar del id de post, aparezca el título del mismo por temas de <a title="Posicionamiento en buscadores" href="http://www.tecnoretales.com/categoria/internet/seo-internet/">posicionamiento en buscadores</a>.</p>
<p>El enrutameinto se puede definir por aplicación modificando el archivo <em>/var/www/blog/apps/&lt;aplicacion&gt;/config/routing.yml</em>. Por defecto, este archivo contiene unas reglas básicas que modificaremos para dar a la URL el aspecto que deseemos.</p>
<p>Nuestro objetivo es conseguir una url de este estilo:</p>
<pre>http://localhost/blog/post/lorem-ipsum-et-dolor/12</pre>
<p>Para ello, añadiremos la siguiente entrada al archivo de routing después de el bloque <em>default_index</em>:</p>
<pre>show_by_title:
  url:     /post/:title/:id
  param:   { module: post, action: permalink }</pre>
<p>Esto, enviará cualquier URL de el estilo definido a la acción permalink que debemos crear en la clase <em>actions.class.php</em> del módulo <em>post</em>:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"> &nbsp;<span class="coMULTI">/**</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp; &nbsp;* Executes permalink action</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp; &nbsp;*/</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw2">public</span> <span class="kw2">function</span> executePermalink<span class="br0">&#40;</span><span class="br0">&#41;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="re0">$this</span>-&gt;<span class="me1">forward</span><span class="br0">&#40;</span><span class="st0">&#8216;post&#8217;</span>, <span class="st0">&#8217;show&#8217;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>En este caso, nos basta con redireccionar a la acción show ya que en el método que muestra la noticia se recogerá el identificador y pintará los datos. Para más información sobre routing, puedes visitar la <a title="Guía Symfony" href="http://www.librosweb.es/symfony_1_1/capitulo9/configuracion_del_sistema_de_enrutamiento.html" target="_blank">guía de Symfony</a>.</p>
<p>Con esto tienes unas priemras nociones para poner en marcha una aplicación, en cualquier caso, puedes aprender más sobre Symfony en la documentación oficial, en el <a title="Grupo Symfony de Google" href="http://groups.google.es/group/symfony-es" target="_blank">grupo Symfony de Google</a> o en futuros artículos de este blog <img src='http://www.tecnoretales.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<!-- google_ad_section_end -->]]></content:encoded>
			<wfw:commentRss>http://www.tecnoretales.com/programacion/mi-primer-proyecto-con-symfony-127-parte-ii/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Mi primer proyecto con Symfony 1.2.7 (parte I)</title>
		<link>http://www.tecnoretales.com/programacion/mi-primer-proyecto-con-symfony-127-parte-i/</link>
		<comments>http://www.tecnoretales.com/programacion/mi-primer-proyecto-con-symfony-127-parte-i/#comments</comments>
		<pubDate>Thu, 21 May 2009 13:24:34 +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=299</guid>
		<description><![CDATA[Después de ver que es Symfony e instalar Symfony en nuestra máquina, voy a poner los pasos que he seguido, y los problemas que me he encontrado (junto con su resolución) para crear mi primer proyecto con Symfony.
Antes de ponernos manos a la obra, es imporatante entender como estructura Symfony el código. Todo proyecto creado [...]]]></description>
			<content:encoded><![CDATA[<!-- google_ad_section_start --><p><img class="alignleft size-full wp-image-319" title="Symfony Logo" src="http://www.tecnoretales.com/wp-content/uploads/2009/05/symfony-logo.png" alt="Symfony Logo" width="38" height="39" />Después de ver <a title="Qué es Symfony" href="http://www.tecnoretales.com/linux/que-es-symfony/">que es Symfony</a> e <a title="Instalar Symfony" href="http://www.tecnoretales.com/programacion/instalar-symfony/">instalar Symfony</a> en nuestra máquina, voy a poner los pasos que he seguido, y los problemas que me he encontrado (junto con su resolución) para <strong>crear mi primer proyecto</strong> con Symfony.</p>
<p>Antes de ponernos manos a la obra, es imporatante entender como estructura Symfony el código. Todo proyecto creado por Symfony consta de una serie de carpetas y archivos que contienen el código base del framework. El árbol de carpetas de un proyecto es:</p>
<p style="text-align: center;"><img class="aligncenter size-full wp-image-304" title="Árbol de directorios Symfony" src="http://www.tecnoretales.com/wp-content/uploads/2009/05/symfony-project-tree.png" alt="Árbol de directorios Symfony" width="202" height="412" /></p>
<p>A su vez, los proyectos están divididos en aplicaciones y módulos, los cuales, <span style="text-decoration: underline;">suelen</span> coincidir con las tablas de nuestra base de datos. En este primer proyecto, haremos un blog muy simple y le pondremos el nombre <strong>blog</strong> (para ser original), a su vez, estará formado por dos aplicaciones, el <strong>frontend</strong> (o la parte visible para los usuarios comunes) y el <strong>backend</strong> (el panel de administración). Por último, cada una de las aplicaciones tendrá dos modulos: <strong>post</strong> y <strong>comment</strong>:</p>
<div id="attachment_327" class="wp-caption aligncenter" style="width: 490px"><img class="size-full wp-image-327" title="Estructura proyecto Symfony" src="http://www.tecnoretales.com/wp-content/uploads/2009/05/symfony_diagrama.jpg" alt="Estructura proyecto Symfony" width="480" height="141" /><p class="wp-caption-text">Estructura proyecto Symfony</p></div><br />
<span id="more-299"></span></p>
<h3>Base de datos del proyecto</h3>
<p>Para la base de datos de este primer proyecto, crearemos un modelo muy simple que constará de una tabla de posts y una tabla de comentarios con una relación 1:n, puesto que un post puede tener n comentarios.</p>
<p><div id="attachment_326" class="wp-caption aligncenter" style="width: 552px"><img class="size-full wp-image-326" title="Symfony DB" src="http://www.tecnoretales.com/wp-content/uploads/2009/05/symfony_db.gif" alt="Base de datos" width="542" height="209" /><p class="wp-caption-text">Base de datos</p></div>
<h3>Creando el proyecto</h3>
<p>Una vez tenemos clara la definición de la base de datos, las aplicaciones y los módulos del proyecto, podemos empezar a dar forma a nuestro código.</p>
<ol>
<li>El primer paso será crear mediante el script que nos proporciona Symfony, un proyecto vacío, para ello, creamos una carpeta <em>blog</em> en, por ejemplo, <em>/var/www/</em> y ejecutamos symfony generate:project &lt;project&gt;:
<pre>mkdir -p /var/www/blog/
cd /var/www/blog/
symfony generate:project blog</pre>
<p>Esto nos habrá creado todo el árbol de directorios y archivos necesarios para poner en marcha nuestra web con este framework.</p>
<p><strong>NOTA!! Dependiendo del sistema operativo y de la instalación realizada, puede ser necesario utilizar el prefijo php antes de cada comando <em>symfony</em> (por ejemplo: &gt; php symfony new blog)</strong></li>
<li>Ahora, le pediremos a Symfony que nos genere las dos aplicaciones definidas anteriormente: frontend y backend
<pre>symfony generate:app --escaping-strategy=on --csrf-secret=UniqueSecret frontend
symfony generate:app --escaping-strategy=on --csrf-secret=UniqueSecret backend</pre>
<p>Al llamar a la tarea generate:app, también hemos pasado dos opciones relacionadas con la seguridad:</p>
<ul>
<li>&#8211;escaping-strategy: Permite escapar la salida para evitar <a title="Ataques XSS" href="http://es.wikipedia.org/wiki/Cross-site_scripting" target="_blank">ataques XSS</a></li>
<li>&#8211;csrf-secret: Permite tokens de sesión en los formularios para prevenir los <a title="Ataques CSRF" href="http://es.wikipedia.org/wiki/Cross_Site_Request_Forgery" target="_blank">ataques CSRF</a></li>
</ul>
</li>
<li>El siguiente paso, será conectar nuestra aplicación con la base de datos, para ello, Symfony dispone de un archivo de configuración <strong>/var/www/blog/config/databases.yml</strong> en el que le indicaremos donde está localizada, a que base de datos y con que usuario y contraseña lo deberá hacer.Para este caso, daremos por hecho que la base de datos es MySQL, se encuentra en la máquina local y que estará codificada en utf8. Abrimos el archivo y modificamos los valores que pongo en negrita:
<pre>all:
  propel:
    class:        sfPropelDatabase
    param:
      classname:  PropelPDO
      dsn:        mysql:dbname=<strong>DB-NAME</strong>;host=localhost
      username:   <strong>DB-USER</strong>
      password:   <strong>DB-PASSWORD</strong>
      encoding:   utf8
      persistent: true
      pooling:    true</pre>
<p>Con esto, ya tenemos configurado nuestro proyecto con la base de datos!!</li>
<li>Una vez definida la conexión con la base de datos, creamos en el archivo <strong>/var/www/blog/config/schema.yml</strong> el esquema de la base de datos que representa el modelo de datos del proyecto:
<pre>propel:
  post:
    _attributes:   { phpName: Post }
    id:
    title:         varchar(255)
    excerpt:       longvarchar
    body:          longvarchar
    created_at:
    updated_at:
  comment:
    _attributes:   { phpName: Comment }
    id:
    post_id:
    author:        varchar(255)
    email:         varchar(255)
    body:          longvarchar
    created_at:
    updated_at:</pre>
<p>Symfony, permite insertar una serie de opciones o atributos en su esquema de la base de datos, como por ejemplo <em>phpName</em>, que indica el nombre de la clase PHP utilizada para manejar cada tabla, además de ser capaz de deducir información del typo de campo a partir del nombre de la columna. Si por ejemplo una columna se llama id, salvo que se le indique lo contrario, Symfony supone que es la clave primaria de la tabla y, por tanto, que es de tipo entero, que no puede tomar valores null y que su valor se autoincrementa.</p>
<p>Puedes ver más información sobre la syntaxis del esquema en la <a title="Sintaxis extendida del esquema" href="http://www.librosweb.es/symfony_1_0/capitulo8/sintaxis_extendida_del_esquema.html" target="_blank">guía Symfony definitiva</a>.</li>
<li>Ahora que tenemos definido el esquema, ejecutamos el comando <strong>propel:build-model</strong> para generar en la carpeta <em>/var/www/blog/lib/model</em> las clases que se encargan de manejar la base de datos
<pre>symfony propel:build-model</pre>
<p><strong>NOTA!!</strong> Si en este punto, aparece un error <em><strong>&#8220;Could not perform XLST transformation.  Make sure PHP has been compiled/configured to support XSLT.&#8221;</strong></em> es debido a que no tienes instalada la extensión xsl para PHP. Desde Ubuntu puedes instalarla con <em>sudo apt-get instal php5-xsl</em></li>
<li>Ya estamos listos para decirle a symfony que nos genere el script de creación de base de datos y lanzarlo:
<pre>symfony propel:build-sql
mysql -u <strong>DB-USER</strong> -p <strong>DB-NAME</strong> &lt; /var/www/blog/data/sql/lib.model.schema.sql</pre>
<p><strong>Nota!!</strong> Si antes de empezar el proyecto Symfony ya dispones de una base de datos, puedes hacer el trabajo inverso: generar el esquema y las clases PHP a partir de una base de datos existente.</li>
<li>Nos vamos a nuestro navegador y visitamos la dirección <a href="http://localhost/blog/" target="_blank"><strong>http://localhost/blog/</strong></a>,si todo ha ido bien, deberíamos estar viendo una página similar a esta:<br />
<img class="aligncenter size-full wp-image-312" title="Symfony Welcome Page" src="http://www.tecnoretales.com/wp-content/uploads/2009/05/symfony-firstpage.png" alt="Symfony Welcome Page" width="300" height="234" /></p>
<p><strong>Nota!!</strong> Si la página te aparece sin imágenes ni estilos, bájate el <a title="SandBox 1.2.7" href="http://www.symfony-project.org/get/sf_sandbox_1_2.zip">archivo comprimido de Symfony Sandbox</a> y descompríme <strong>sólo</strong> la carpeta <strong>/sf_sandbox/web/sf/</strong> dentro de <strong>/var/www/blog/web/</strong>, con esto verás las imágenes y estilos del entorno recién creado.</li>
</ol>
<p>Para que no me quede este post demasiado largo, lo he dividido en dos. En la segunda parte de &#8220;<a title="Mi primer proyecto con Symfony 1.2.7 (parte II)" href="http://www.tecnoretales.com/programacion/mi-primer-proyecto-con-symfony-127-parte-ii/">Mi primer proyecto con Symfony 1.2.7</a>&#8221; veremos como dar forma a la parte pública y privada, hacer uso del scaffolding para generar las acciones comunes CRUD (Create, Read, Update, Delete) o configurar el aspecto de las URLs.</p>
<!-- google_ad_section_end -->]]></content:encoded>
			<wfw:commentRss>http://www.tecnoretales.com/programacion/mi-primer-proyecto-con-symfony-127-parte-i/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Instalar Symfony</title>
		<link>http://www.tecnoretales.com/programacion/instalar-symfony/</link>
		<comments>http://www.tecnoretales.com/programacion/instalar-symfony/#comments</comments>
		<pubDate>Tue, 19 May 2009 15:10:28 +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=281</guid>
		<description><![CDATA[El otro día os comentaba que és Symfony. Hoy os voy a explicar como instalarlo paso a paso de cuatro modos distintos, mediante PEAR, de los repositorios oficiales de Ubuntu/Debian, desde los repositorios Subversion y descargandonos el archivo de la web.
Cualquiera de las opciones que aquí os expondré són igualmente válidas para acondicionar nuestra máquina [...]]]></description>
			<content:encoded><![CDATA[<!-- google_ad_section_start --><p><img class="alignleft size-full wp-image-283" title="Symfony Logo" src="http://www.tecnoretales.com/wp-content/uploads/2009/05/symfony_180.png" alt="Symfony Logo" width="180" height="130" />El otro día os comentaba <a title="Qué es Symfony" href="http://www.tecnoretales.com/linux/que-es-symfony/">que és Symfony</a>. Hoy os voy a explicar como <strong>instalarlo paso a paso</strong> de cuatro modos distintos, mediante PEAR, de los repositorios oficiales de Ubuntu/Debian, desde los repositorios Subversion y descargandonos el archivo de la web.</p>
<p>Cualquiera de las opciones que aquí os expondré són igualmente válidas para acondicionar nuestra máquina y usar Symfony, sin embargo, recomiendo instalarlo mediante PEAR o de los repositorios de Ubuntu/Debian para facilitar la actualización posterior.</p>
<p><span id="more-281"></span></p>
<h3>Instalación PEAR</h3>
<p>Esta instalación requiere de la versión de PEAR 1.4.0 o superior.</p>
<ol>
<li>Añadimos el channel de Symfony escribiendo desde línea de comandos:
<pre>pear channel-discover pear.symfony-project.com</pre>
</li>
<li>Instalamos la última versión (actualmente la 1.2.7) ejecutando este comando con permisos de administrador:
<pre>sudo <code>pear install symfony/symfony-1.2.7</code></pre>
</li>
</ol>
<h3>Desde los repositorios oficiales de Ubuntu/Debian</h3>
<p>Podemos instalar este completo framework PHP en Ubuntu y Debian haciendo:</p>
<ol>
<li>Añadimos en el arcihvo <em>/etc/apt/sources.list</em> el repositorio de Symfony
<pre># Symfony
deb http://www.symfony-project.org/get debian/</pre>
</li>
<li>Actualizamos los listados de nuestra Ubuntu ejecutando con permisos de administrador:
<pre>sudo <code>apt-get update</code></pre>
</li>
<li>Por último, instalamos Symfony ejecutando:
<pre>sudo <code>apt-get install php5-symfony</code></pre>
</li>
</ol>
<h3>Desde los repositorios Subversion</h3>
<p>Symfony pone a nuestra disposición sus repositorios Subversion de código para que podamos hacer un checkout del código:</p>
<ol>
<li>Creamos una carpeta en un lugar accesible desde nuestro navegador, por ejemplo <em>/var/www/&lt;folder&gt;</em>:
<pre>mkdir -p /var/www/&lt;folder&gt;
cd /var/www/&lt;folder&gt;</pre>
</li>
<li>Hacemos el checkout del código:
<pre><code>svn co http://svn.symfony-project.com/branches/1.2</code></pre>
</li>
</ol>
<h3>Descargando desde la web</h3>
<p>Por último, también podemos ir a la página oficial de Symfony y descargarnos el último archivo estable. Abrimos una línea de comandos y hacemos:</p>
<ol>
<li>Descargamos el último archivo estable (en mi caso la versión 1.2.7):
<pre>wget http://www.symfony-project.org/get/symfony-1.2.7.tgz</pre>
</li>
<li>Creamos una carpeta en un lugar accesible desde nuestro navegador, por ejemplo <em>/var/www/&lt;folder&gt;</em>:
<pre>mkdir -p /var/www/&lt;folder&gt;
cd /var/www/&lt;folder&gt;</pre>
</li>
<li>Descomprimimos el archivo en ella:
<pre>tar xvzf /path/to/symfony-1.2.7.tgz</pre>
</li>
</ol>
<p>Si bien, la documentación oficial de este framework es bastante extensa y clara, para cualquier duda, visitarla haciendo <a title="Documentación Oficial Symfony" href="http://www.symfony-project.org/doc/1_2/">click aquí</a>.</p>
<!-- google_ad_section_end -->]]></content:encoded>
			<wfw:commentRss>http://www.tecnoretales.com/programacion/instalar-symfony/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

