<?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>BLOG PUENTES DIAZ &#187; Software Libre</title>
	<atom:link href="http://blog.puentesdiaz.com.ar/category/software-libre/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.puentesdiaz.com.ar</link>
	<description>Otro sitio más de Puentes Diaz</description>
	<lastBuildDate>Thu, 04 Aug 2011 15:57:45 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Bootear Multiples OS con ISOs desde PENDRIVE</title>
		<link>http://blog.puentesdiaz.com.ar/2011/07/01/bootear-multiples-os-con-isos-desde-pendrive/</link>
		<comments>http://blog.puentesdiaz.com.ar/2011/07/01/bootear-multiples-os-con-isos-desde-pendrive/#comments</comments>
		<pubDate>Fri, 01 Jul 2011 15:47:57 +0000</pubDate>
		<dc:creator>Puentes Diaz</dc:creator>
				<category><![CDATA[Software Libre]]></category>
		<category><![CDATA[Tecnología IT]]></category>

		<guid isPermaLink="false">http://blog.puentesdiaz.com.ar/?p=316</guid>
		<description><![CDATA[El título puede ser medio largo, pero es eso sin mas rodeos. Crear un Pendrive para bootear distintos Sistemas Operativos, usando solo las imagenes ISO, sin necesidad de instalar nada. Esta es una gran herramienta para aquellos que deseen probar &#8230; <a href="http://blog.puentesdiaz.com.ar/2011/07/01/bootear-multiples-os-con-isos-desde-pendrive/">Sigue leyendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>El título puede ser medio largo, pero es eso sin mas rodeos. Crear un Pendrive para bootear distintos Sistemas Operativos, usando solo las imagenes ISO, sin necesidad de instalar nada. Esta es una gran herramienta para aquellos que deseen probar los sabores de Linux por ejemplo, que siendo usuarios de Windows, aun no saben que elegir y son temerosos de instalar otro OS en sus discos duros.</p>
<p>Entonces para ellos, tenemos YUMI ( <a href="http://www.pendrivelinux.com/yumi-multiboot-usb-creator/">web</a> ) ( <a href="http://www.pendrivelinux.com/downloads/YUMI/YUMI-0.0.2.3.exe">Descarga</a> ) .</p>
<p><img title="YUMI - Multiboot USB Creator" src="http://www.pendrivelinux.com/wp-content/uploads/YUMI-Multiboot-USB-Creator.png" alt="YUMI - Multiboot USB Creator" width="450" height="350" /></p>
<p>Como podemos apreciar, solo hay que conectar el pendrive al puerto USB, lo que nos permitirá tener una Unidad de Disco, que debemos seleccionar, y luego elegir que sistema deseamos, para terminar un tercer paso en la búsqueda de la imagen ISO.</p>
<p>Ejecutando una segunda vez YUMI podremos cargar el otro sistema de nuestra preferencia.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.puentesdiaz.com.ar/2011/07/01/bootear-multiples-os-con-isos-desde-pendrive/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Salve GNU/Linux</title>
		<link>http://blog.puentesdiaz.com.ar/2010/10/26/salve-gnulinux/</link>
		<comments>http://blog.puentesdiaz.com.ar/2010/10/26/salve-gnulinux/#comments</comments>
		<pubDate>Tue, 26 Oct 2010 16:00:33 +0000</pubDate>
		<dc:creator>puentesdiaz</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Software Libre]]></category>

		<guid isPermaLink="false">http://blog.puentesdiaz.com.ar/?p=291</guid>
		<description><![CDATA[¿Que título no? En realidad, debemos agradecer a GNU, Linux, EXT4, Ubuntu, y a un programita llamado TESTDISK. Creo que sería imposible explicar cuales fueron las razones. Lo cierto es que la notebook, mostraba que el disco rígido estaba vacío. &#8230; <a href="http://blog.puentesdiaz.com.ar/2010/10/26/salve-gnulinux/">Sigue leyendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>¿Que título no?</p>
<p>En realidad, debemos agradecer a GNU, Linux, EXT4, Ubuntu, y a un programita llamado TESTDISK.</p>
<p>Creo que sería imposible explicar cuales fueron las razones. Lo cierto es que la notebook, mostraba que el disco rígido estaba vacío. Ese es el momento es que uno pensaba porque no compre de una vez  &#8221;ese&#8221; disco externo de 1 o 2 TeraBytes&#8230; para luego pensar que no era para tanto los meses y meses de información guardada.</p>
<p>¿Como sigue esto?</p>
<p>Con la imagen de la última versión de Ubuntu (al día de hoy, la 10.10). Me hice de un PenDrive, (ese pendorcho usb que nadie sabe como se llama), y lo transformamos en un Pendrive de instalación.</p>
<blockquote><p>Recomiendo esta modalidad, pues he notado que tratar de hacerlo desde un CD o DVD, es mas lento, y a veces falla.</p></blockquote>
<p>Desde hace mucho, muchas distribuciones de GNU/Linux, y Ubuntu no es la excepción, se puede bootear y ejecutar el sistema sin necesidad de instalación. Y en este caso, detectó todo, inclusive esa placa de red wifi que no traía los drivers.</p>
<p>Empezamos a googlear, y la comunidad da un montón de buenos tutoriales. Donde se recomienda <a href="http://www.cgsecurity.org/wiki/TestDisk" target="_blank">TESTDISK</a>.</p>
<p>Cuando se descarga, nos damos cuenta que no es un .deb o .rpm, pero no debe importarnos. Solo debemos ejecutar desde consola el ejecutable y con 15 segundos y 4 pasos, se reestablecerá tu Tabla de Particiones, y con ello rebootear para darnos cuenta que la pesadilla pasó.</p>
<p>Todo pero Todo, esta como debería estar. En resumen, TESTDISK, funciona amigos!!!!!!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.puentesdiaz.com.ar/2010/10/26/salve-gnulinux/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP 6: Que hay de nuevo</title>
		<link>http://blog.puentesdiaz.com.ar/2010/04/01/php-6-que-hay-de-nuevo/</link>
		<comments>http://blog.puentesdiaz.com.ar/2010/04/01/php-6-que-hay-de-nuevo/#comments</comments>
		<pubDate>Thu, 01 Apr 2010 13:47:01 +0000</pubDate>
		<dc:creator>puentesdiaz</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Software Libre]]></category>

		<guid isPermaLink="false">http://blog.puentesdiaz.com.ar/?p=233</guid>
		<description><![CDATA[La llegada de PHP6, esta cerca. La promesa de una mejor POO y el soporte UNICODE, es bien conocido. Con Unicode, tendremos una referencia única a cada caracter, así como una lista mas completa&#8230; mas de 99000. Una de las &#8230; <a href="http://blog.puentesdiaz.com.ar/2010/04/01/php-6-que-hay-de-nuevo/">Sigue leyendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>La llegada de PHP6, esta cerca. La promesa de una mejor POO y el soporte UNICODE, es bien conocido.</p>
<p>Con Unicode, tendremos una referencia única a cada caracter, así como una lista mas completa&#8230; mas de 99000.</p>
<p>Una de las formas mas populares de apreciar el cambio, es cuando en el resultado del buscador, aparecen caracteres &#8220;raros&#8221; o expresiones en otro idioma, o frases en árabe, chino, etc</p>
<p>Una idea de lo que podremos lograr, es con un ejemplo del Unicode composition, que permitirá crear caracteres nuevos a medida que cada lenguaje o idioma evolucione.</p>
<p><a href="http://i.zdnet.com/blogs/php31.jpg"></a></p>
<div id="attachment_235" class="wp-caption alignnone" style="width: 310px"><a href="http://blog.puentesdiaz.com.ar/files/2010/04/PHP6unicode.jpg"><img class="size-medium wp-image-235" src="http://blog.puentesdiaz.com.ar/files/2010/04/PHP6unicode-300x180.jpg" alt="" width="300" height="180" /></a><p class="wp-caption-text">unicode</p></div>
<p>La internacionalización será mas fácil, y la Transliteración, nos permite escribir en un idioma y convertirlo a otro, para que lo podamos pronunciar sin vergüenza ninguna. Con PHP6, solo lleva un par de lineas de código.</p>
<p><a href="http://blog.puentesdiaz.com.ar/files/2010/04/php6unicode2.jpg"><img class="alignnone size-medium wp-image-236" src="http://blog.puentesdiaz.com.ar/files/2010/04/php6unicode2-300x104.jpg" alt="" width="300" height="104" /></a></p>
<p>El TextIterator es una nueva característica de PHP 6, puedes iterar en cada punto, caracter, palabra o linea, y en ambos sentidos. Y poder cortarlos es mucho más fácil.</p>
<p>El ROADMAP, se esta actualizando pero imagino que pronto tendremos una release de PHP6, aunque ello no impida un PHP5.4</p>
<p>Fuente : http://blogs.zdnet.com/BTL/?p=9313</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.puentesdiaz.com.ar/2010/04/01/php-6-que-hay-de-nuevo/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Symfony 2 para phpBB4</title>
		<link>http://blog.puentesdiaz.com.ar/2010/03/02/symfony-2-para-phpbb4/</link>
		<comments>http://blog.puentesdiaz.com.ar/2010/03/02/symfony-2-para-phpbb4/#comments</comments>
		<pubDate>Tue, 02 Mar 2010 18:00:47 +0000</pubDate>
		<dc:creator>puentesdiaz</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Software Libre]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://blog.puentesdiaz.com.ar/?p=224</guid>
		<description><![CDATA[En un reciente articulo de phpBB, se explica el porque se eligió Symfony 2, como base de desarrollo del nuevo phpBB4. Sobre Symfony 2 : http://symfony-reloaded.org Código http://github.com/symfony ¿Qué es Symfony 2? Symfony 2 es una reescritura completa de su &#8230; <a href="http://blog.puentesdiaz.com.ar/2010/03/02/symfony-2-para-phpbb4/">Sigue leyendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>En un reciente articulo de phpBB, se explica el porque se eligió Symfony 2, como base de desarrollo del nuevo phpBB4.</p>
<p>Sobre Symfony 2 : <a title="http://symfony-reloaded.org" rel="nofollow" href="http://symfony-reloaded.org/">http://symfony-reloaded.org<br />
</a>Código <a title="http://github.com/symfony" rel="nofollow" href="http://github.com/symfony">http://github.com/symfony</a></p>
<p><a id="Discussion" name="Discussion"></a></p>
<h2>¿Qué es Symfony 2?</h2>
<p>Symfony 2 es una reescritura completa de su código original, el cual se enfoca en resolver los problemas de las anteriores versiones ( 1.0 a  1.4). Symfony, se convirtió en una herraminta apreciada por la comunidad PHP. Tiene una gran cantidad de plugins que resuelven distintos desafios y promete un mejor uso de los recursos que como lo hacia symfony 1.</p>
<h2>¿Porque Symfony 2 para phpBB4?</h2>
<p>La siguiente lista explica en cada punto las razones. La misma esta basada en los items de los Principios de Programación de phpBB4.</p>
<ul>
<li> <strong>phpBB4</strong>: PHP 5.3+
<ul>
<li> <strong>Symfony 2</strong> fue re-escrito en PHP5.3, consistentemente con el enfoque de phpBB4.</li>
</ul>
</li>
<li> <strong>phpBB4</strong>: Hace uso de namespaces y de la autocarga standar.
<ul>
<li> <strong>Symfony 2</strong> es el primer framework en seguir el autoloading standard de PHP5.3, mejorando la interoperabilidad del proyecto PHP.</li>
</ul>
</li>
<li> <strong>phpBB4</strong>: Código limpio y modular orientado a objetos con clases desacopladas
<ul>
<li> <strong>Symfony 2</strong> es un framework orientado a objetos. De arquitectura simple y fácil API.</li>
</ul>
</li>
<li> <strong>phpBB4</strong>: Los Plugins pueden completamente reemplazar  MODs sin ningun cambio en el código
<ul>
<li> <strong>Symfony 2</strong>: Como se menciono antes Symfony 2 esta en bundles que no necesitan de modificaciones. Symfony 2 hace uso de códifo generado.</li>
</ul>
</li>
<li> <strong>phpBB4</strong>: Usar existentes librerias / frameworks en luhar de reinventar la rueda
<ul>
<li> <strong>Symfony 2</strong>: El uso de un framework como Symfony 2  ya casi permite esto. Además  Symfony 2 digue de cerca al Zend Framework.</li>
</ul>
</li>
<li> <strong>phpBB4</strong>: Fácil integración con software
<ul>
<li> <strong>Symfony 2</strong>: Usando Symfony 2 phpBB4 automaticamente podrá integrarse en un proyecto Symfony cualquiera. El diseño de Symfony 2 también requiere que hagamos phpBB de manera modular,.</li>
</ul>
</li>
<li> <strong>phpBB4</strong>: Escalabilidad (ejecutarse sobre clusters)
<ul>
<li> <strong>Symfony 2</strong>: Symfony tiene una historia de ejecutar grandes services, y Symfony 2 esta diseñado para la alta performance.</li>
</ul>
</li>
<li> <strong>phpBB4</strong>: Consistente con el uso de Dependency Injection
<ul>
<li> <strong>Symfony 2</strong> esta construido alrededor de un Dependency  Injection Container, usando Dependency Injection por todos lados.</li>
</ul>
</li>
<li> <strong>phpBB4</strong>: Pruebas automatizadas: Pruebas Unitarias,  integración de pruebas y pruebas funcionales con PHPUnit, Selenium
<ul>
<li> <strong>Symfony 2</strong> tiene ya las pruebas automatizadas y permite a los proyectos usar cualquier framework de pruebas.</li>
</ul>
</li>
<li> <strong>phpBB4</strong>: Un framework de desarrollo para phpBB (hacer  aplicaciones basadas en phpBB, estandarizar nuestro framework en una libreria)
<ul>
<li> <strong>Symfony 2</strong> es un framework y tiene mas sentido que hacer uno específico para phpBB. Partes de phpBB serán reusables.</li>
</ul>
</li>
</ul>
<p>Es absolutamente asombroso como Symfony 2 coincide con los requisitos de phpBB4.</p>
<p><a id="What_else_can_Symfony_2_give_us.3F" name="What_else_can_Symfony_2_give_us.3F"></a></p>
<h2>¿Que otra cosa puede Symfony 2 dar?</h2>
<p>Ya que su comunidad es muy grande, podemos contar con mas desarrolladores y mas aportes. Los clientes necesitan una integración de un foro dentro de un proyecto Symfony y es problema común para los programadores. En vez de crear un propio, se puede usar phpBB integrado. Los desarrolladores con esta necesidad pueden ayudar a phpBB.</p>
<p>Para conocer mas <a title="http://symfony-reloaded.org" rel="nofollow" href="http://symfony-reloaded.org/">http://symfony-reloaded.org</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.puentesdiaz.com.ar/2010/03/02/symfony-2-para-phpbb4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Richard Stallman y Roberto Puentes Díaz en Córdoba</title>
		<link>http://blog.puentesdiaz.com.ar/2009/08/24/richard-stallman-y-roberto-puentes-diaz-en-cordoba/</link>
		<comments>http://blog.puentesdiaz.com.ar/2009/08/24/richard-stallman-y-roberto-puentes-diaz-en-cordoba/#comments</comments>
		<pubDate>Mon, 24 Aug 2009 17:54:48 +0000</pubDate>
		<dc:creator>puentesdiaz</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Software Libre]]></category>

		<guid isPermaLink="false">http://www.puentesdiaz.com.ar/blog/?p=163</guid>
		<description><![CDATA[Ayer Domindo 23, el señor Richard Stallman, tuvo el placer de tomarse una foto con su servidor. Cuando RMS me conoció Bueno, saliendo del tono de humor/ego. Decir que la conferencia es todo un exito, Felicitaciones a la Fundacion Via &#8230; <a href="http://blog.puentesdiaz.com.ar/2009/08/24/richard-stallman-y-roberto-puentes-diaz-en-cordoba/">Sigue leyendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Ayer Domindo 23, el señor Richard Stallman, tuvo el placer de tomarse una foto con su servidor.</p>
<dl>
<dt><a href="http://photos-1.getdropbox.com/i/o/Zrz5dLSmyoXM9aIIAthIO719aeEfOBjQUA9XBQtuPlI"><img src="http://photos-1.getdropbox.com/i/o/Zrz5dLSmyoXM9aIIAthIO719aeEfOBjQUA9XBQtuPlI" alt="Cuando RMS me conoció" width="408" height="355" /></a></dt>
</dl>
<div class="mceTemp">
<dl>
<dd>Cuando RMS me conoció</dd>
</dl>
</div>
<p>Bueno, saliendo del tono de humor/ego. Decir que la conferencia es todo un exito, Felicitaciones a la Fundacion Via Libre, UNC, y la Ciudad de Córdoba. Desde ayer RMS es visitante ilustre.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.puentesdiaz.com.ar/2009/08/24/richard-stallman-y-roberto-puentes-diaz-en-cordoba/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Como Bootear desde en una Maquina Virtual VirtualBox</title>
		<link>http://blog.puentesdiaz.com.ar/2008/11/13/como-bootear-desde-en-una-maquina-virtual-virtualbox/</link>
		<comments>http://blog.puentesdiaz.com.ar/2008/11/13/como-bootear-desde-en-una-maquina-virtual-virtualbox/#comments</comments>
		<pubDate>Thu, 13 Nov 2008 12:50:24 +0000</pubDate>
		<dc:creator>puentesdiaz</dc:creator>
				<category><![CDATA[Software Libre]]></category>
		<category><![CDATA[Tecnología IT]]></category>

		<guid isPermaLink="false">http://www.puentesdiaz.com.ar/blog/?p=124</guid>
		<description><![CDATA[Como Bootear desde en una Maquina Virtual VirtualBox Si llegaste hasta aqui es porque, seguro que no encontraste la forma de seleccionar tu pendrive en el orden de booteo. Ademas parece que VB no da soporte aun en los BIOS &#8230; <a href="http://blog.puentesdiaz.com.ar/2008/11/13/como-bootear-desde-en-una-maquina-virtual-virtualbox/">Sigue leyendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<h3 class="post-title entry-title">Como Bootear desde en una Maquina Virtual VirtualBox</h3>
<p><a href="http://upload.wikimedia.org/wikipedia/en/thumb/d/d5/Virtualbox_logo.png/96px-Virtualbox_logo.png"><img style="margin: 0pt 10px 10px 0pt;float: left;cursor: pointer;width: 134px;height: 134px" src="http://upload.wikimedia.org/wikipedia/en/thumb/d/d5/Virtualbox_logo.png/96px-Virtualbox_logo.png" border="0" alt="" /></a><br />
Si llegaste hasta aqui es porque, seguro que no encontraste la forma de seleccionar tu pendrive en el orden de booteo. Ademas parece que VB no da soporte aun en los BIOS virtuales&#8230;</p>
<p>Por eso, podemos probar esto:</p>
<p>1) Crea una nueva Maquina Virtual<br />
b) En la seccion &#8220;Floppy&#8221; del panel derecho, ingresa.<br />
c) Activa &#8220;Mount Floppy Drive&#8221;, y de la lista desplegable &#8220;Host Floppy Device&#8221;, selecciona la letra o ruta de tu pendrive (e: en windows, por ej:; en linux puede ser /dev/sdxx)</p>
<p>Listo!.<br />
Saludos</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.puentesdiaz.com.ar/2008/11/13/como-bootear-desde-en-una-maquina-virtual-virtualbox/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Symfony 1.2 Bondades de Doctrine</title>
		<link>http://blog.puentesdiaz.com.ar/2008/11/07/symfony-12-bondades-de-doctrine/</link>
		<comments>http://blog.puentesdiaz.com.ar/2008/11/07/symfony-12-bondades-de-doctrine/#comments</comments>
		<pubDate>Fri, 07 Nov 2008 12:53:47 +0000</pubDate>
		<dc:creator>puentesdiaz</dc:creator>
				<category><![CDATA[Software Libre]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://www.puentesdiaz.com.ar/blog/?p=95</guid>
		<description><![CDATA[Un Gran Agradecimiento Una gran cantidad de cosas impresionantes, se han añadido recientemente a la proxima gran entrega de symfony 1.2. Fabien ha trabajado muy duro para agregar sin dudas las más sofisticadas características que cualquier otro framework PHP pudiera &#8230; <a href="http://blog.puentesdiaz.com.ar/2008/11/07/symfony-12-bondades-de-doctrine/">Sigue leyendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<h2>Un Gran Agradecimiento</h2>
<p>Una gran cantidad de cosas impresionantes, se han añadido recientemente a la proxima gran entrega de symfony 1.2. Fabien ha trabajado muy duro para agregar sin dudas las más sofisticadas características que cualquier otro framework PHP pudiera tener hoy en día. No sólo son características agradables sino que fueron implementadas Orientada a Objeto por lo que ha sido sencillo para mi implmentar algunas características con otro ORM, <a href="http://www.doctrine-project.org">Doctrine</a>.Todo esto se hizo con muy poco trabajo de mi parte. Por lo tanto, doy muchas gracias a él y disfruta de este artículo.</p>
<h2>Ejemplo del mundo real</h2>
<p>En este artículo voy a empezar desde el principio con un nuevo proyecto symfony 1.2 para que puedas ponerte en marcha con Doctrine. Vamos a utilizar un esquema típico de tu sistema de gestión de contenidos. El esquema consta de los artículos, los autores y categorías donde los artículos son internacionalizados.</p>
<h2>Comienza tu Proyecto</h2>
<p>En primer lugar necesitas inicializar un nuevo proyecto symfony 1.2 y inicializar un app backend. Asegúrate de que estás utilizando el último código del svn pues beta1 no incluye esta funcionalidad de Doctrine.</p>
<p><strong>Generar tu proyecto</strong></p>
<pre>mkdir cms
cd cms
symfony generate:project cms
</pre>
<p><strong>Generar la aplicación backend</strong></p>
<pre>symfony generate:app backend</pre>
<h2>Todo el mundo encienda su Doctrine</h2>
<p>Ahora tenemos que habilitar Doctrine y desactivar Propel <img src='http://blog.puentesdiaz.com.ar/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Edita tu <code>config/ProjectConfiguration.class.php</code> y agregue el código siguiente a tu función <code>setup()</code>.</p>
<pre>
public function setup()
{
  $this-&gt;enablePlugins(array('sfDoctrinePlugin'));
  $this-&gt;disablePlugins(array('sfPropelPlugin'));
}
</pre>
<p>Ahora que Doctrine está habilitado podemos enumerar las tareas disponibles de Doctrine:</p>
<pre>
./symfony list doctrine

Available tasks for the "doctrine" namespace:
  :build-all                   Generates Doctrine model, SQL and initializes the database (doctrine-build-all)
  :build-all-load              Generates Doctrine model, SQL, initializes database, and load data (doctrine-build-all-load)
  :build-all-reload            Generates Doctrine model, SQL, initializes database, and load data (doctrine-build-all-reload)
  :build-all-reload-test-all   Generates Doctrine model, SQL, initializes database, load data and run all test suites (doctrine-build-all-reload-test-all)
  :build-db                    Creates database for current model (doctrine-build-db)
  :build-filters               Creates filter form classes for the current model
  :build-forms                 Creates form classes for the current model (doctrine-build-forms)
  :build-model                 Creates classes for the current model (doctrine-build-model)
  :build-schema                Creates a schema from an existing database (doctrine-build-schema)
  :build-sql                   Creates SQL for the current model (doctrine-build-sql)
  :data-dump                   Dumps data to the fixtures directory (doctrine-dump-data)
  :data-load                   Loads data from fixtures directory (doctrine-load-data)
  :dql                         Execute a DQL query and view the results (doctrine-dql)
  :drop-db                     Drops database for current model (doctrine-drop-db)
  :generate-admin              Generates a Doctrine admin module
  :generate-migration          Generate migration class (doctrine-generate-migration)
  :generate-migrations-db      Generate migration classes from existing database connections (doctrine-generate-migrations-db, doctrine-gen-migrations-from-db)
  :generate-migrations-models  Generate migration classes from an existing set of models (doctrine-generate-migrations-models, doctrine-gen-migrations-from-models)
  :generate-module             Generates a Doctrine module (doctrine-generate-crud, doctrine:generate-crud)
  :generate-module-for-route   Generates a Doctrine module for a route definition
  :insert-sql                  Inserts SQL for current model (doctrine-insert-sql)
  :migrate                     Migrates database to current/specified version (doctrine-migrate)
  :rebuild-db                  Creates database for current model (doctrine-rebuild-db)
</pre>
<h2>El Esquema</h2>
<p>Ahora empieza la diversión. Tenemos Doctrine habilitado por lo que la primera cosa que necesitamos es definir nuestro esquema del CMS en <code>config/doctrine/schema.yml</code>.</p>
<pre>---
Article:
  actAs:
    Timestampable:
    I18n:
      fields: [title, content]
  columns:
    author_id: integer
    status:
      type: enum
      values: [Draft, Published]
      notnull: true
    title:
      type: string(255)
      notnull: true
    content:
      type: clob
      notnull: true
    is_on_homepage: boolean
    published_at: timestamp
  relations:
    Author:
      foreignAlias: Articles
    Categories:
      class: Category
      refClass: ArticleCategory
      foreignAlias: Articles
&nbsp;
Category:
  columns:
    name:
      type: string(255)
      notnull: true
&nbsp;
Author:
  columns:
    name:
      type: string(255)
      notnull: true
    about: string(1000)
&nbsp;
ArticleCategory:
  columns:
    article_id: integer
    category_id: integer
  relations:
    Article:
      foreignAlias: ArticleCategories
    Category:
      foreignAlias: ArticleCategories
&nbsp;</pre>
<h2>Datos Fixtures</h2>
<p>Tenemos nuestro esquema, ahora necesitamos algunos datos para ponerlo a prueba por lo que copia de los siguientes YAML en <code>data/fixtures/data.yml</code></p>
<pre>
---
Article:
  Article_1:
    Author: jwage
    status: Published
    is_on_homepage: true
    published_at: ''
    Categories: [article, ontheedge]
    Translation:
      en:
        title: symfony 1.2 and Doctrine
        content: Article about the new Doctrine integration in symfony 1.2
      fr:
        title: symfony 1.2 et doctrine
        content: Article sur l'intégration de Doctrine dans symfony 1.2

Author:
  jwage:
    name: Jonathan H. Wage
    about: Jonathan is the lead developer of the Doctrine project and is also a core contributor to the symfony project.

Category:
  article:
    name: Article
  tutorial:
    name: Tutorial
  ontheedge:
    name: Living on the edge
 </pre>
<h2>Desarrollo y Pruebas</h2>
<p>Ahora que tenemos nuestro esquema y los datos tenemos todo lo que necesitamos para inicializar nuestra base de datos, modelos, formularios, datos, etc. Esto puede ser hecho con el muy simplemente comando siguiente:</p>
<pre>./symfony doctrine:build-all-reload --no-confirmation
&gt;&gt; doctrine  dropping databases
&gt;&gt; doctrine  creating databases
&gt;&gt; doctrine  generating model classes
&gt;&gt; doctrine  generating sql for models
&gt;&gt; doctrine  generating form classes
&gt;&gt; doctrine  generating filter form classes
&gt;&gt; doctrine  created tables successfully
&gt;&gt; doctrine  loading data fixtures from "/Us...ymfony12doctrine/data/fixtures"
</pre>
<p>Eso fue demasiado fácil, cuando se va a poner difícil? Ahora vamos a hacer la inspección con DQL para ver los datos que se cargaron correctamente.</p>
<pre>
./symfony doctrine:dql "FROM Article a, a.Author a2, a.Translation t"
&gt;&gt; doctrine  executing dql query
DQL: FROM Article a, a.Author a2, a.Translation t
found 1 results
-
  id: '1'
  author_id: '1'
  status: Published
  is_on_homepage: true
  published_at: '2008-11-06 04:37:11'
  created_at: '2008-11-06 16:37:11'
  updated_at: '2008-11-06 16:37:11'
  Author:
    id: '1'
    name: 'Jonathan H. Wage'
    about: 'Jonathan is the lead developer of the Doctrine project and is also a core contributor to the symfony project.'
  Translation:
    en:
      id: '1'
      title: 'symfony 1.2 and Doctrine'
      content: 'Article about the new Doctrine integration in symfony 1.2'
      lang: en
    fr:
      id: '1'
      title: 'symfony 1.2 et doctrine'
      content: 'Article sur l''intégration de Doctrine dans symfony 1.2'
      lang: fr
</pre>
<p>Esto puede ser su primer gusto del Doctrine Query Language, también conocido como DQL. Se parece mucho a SQL no? Cierre la boca, que estás babeando.</p>
<p>Para aquellos de ustedes que no quieran escribir cadenas de DQL, no te preocupes tenemos un completo objeto <code>Doctrine_Query</code> para la construcción de tus consultas.</p>
<pre>
$q = Doctrine_Query::create()
  -&gt;from('Article a, a.Author a2, a.Translation t');
$articles = $q-&gt;execute();
</pre>
<h2>Generadores de Admin</h2>
<p>Ahora que tenemos todo construido, podemos empezar a generar algunas cosas con la magia symfony. Vamos a empezar por la definición de la Colecciones de Rutas para la gestión de nuestros artículos, autores y categorías. Abre <code>apps/backend/config/routing.yml</code> en tu editor y pega las siguientes rutas dentro.</p>
<pre>
articles:
  class:         sfDoctrineRouteCollection
  options:
    model:       Article
    module:      articles
    with_show:   true
    collection_actions: { filter: post, batch: post }

categories:
  class:         sfDoctrineRouteCollection
  options:
    model:       Category
    module:      categories
    with_show:   true
    collection_actions: { filter: post, batch: post }

authors:
  class:         sfDoctrineRouteCollection
  options:
    model:       Author
    module:      authors
    with_show:   true
    collection_actions: { filter: post, batch: post }
</pre>
<p>Estas rutas nos permitirán generar un módulo generador de administrador para la gestión de los datos a través de cada uno de los modelos de Doctrine. Ejecute los siguientes comandos para generar los tres módulos.</p>
<pre>
./symfony doctrine:generate-admin backend articles
$ ./symfony doctrine:generate-admin backend categories
$ ./symfony doctrine:generate-admin backend authors
</pre>
<p>Ahora, cuando tiene acceso al modulo <code>categories</code> desde el backend deberías ver lo siguiente.</p>
<p><img src="http://www.symfony-project.org/uploads/assets/doctrine/new_admin_gen.gif" alt="New Admin Generators"></p>
<p>Ahora deseas, perrsonalizar un poco los artículos generados de admin para mostrar sólo una serie de campos en la lista y los filtros del formulario. Puedes hacerlo editando el <code>generator.yml</code> situado en <code>apps/backend/modules/categories/config/generator.yml</code>.</p>
<pre>
config:
  list:
    display:  [title, published_at, is_on_homepage, status]
  filter:
    class:    ArticleFormFilter
    display:  [author_id, status, is_on_homepage, published_at, categories_list]
</pre>
<p>Puedes personalizar los otros módulos de la misma forma.</p>
<p>Ahora, si cambia la URL <code>?sf_culture=fr</code> en su URL el título se mostrará la versión en francés. Debería ver lo siguiente en su navegador cuando levantes hacia arriba el módulo de artículos.</p>
<p><img src="http://www.symfony-project.org/uploads/assets/doctrine/new_admin_gen_articles.gif" alt="New Admin Generators"></p>
<h2>Edición de Traducciones</h2>
<p>Ahora, ¿cómo trabaja la edición de esas traducciones? Si te acuerdas de esto con los antiguos generadores de admin, era casi imposible. Ahora, se trata de una cuestión de añadir una línea de código a nuestro <code>ArticleForm</code>. Todo que tenemos que hacer es embeber/integrar/fusionar el formulario <code>ArticleTranslation</code>. Esto se puede hacer editando <code>lib/form/doctrine/ArticleForm.class.php</code> y añadiendo el código siguiente al <code>configure()</code></p>
<pre>
public function configure()
{
  $this-&gt;embedI18n(array('en', 'fr'));
}
</pre>
<p>Ahora, cuando editas un artículo, verás que tienes la capacidad de editar directamente las traducciones dentro del artículo.</p>
<p><img src="http://www.symfony-project.org/uploads/assets/doctrine/new_admin_gen_i18n.gif" alt="New Admin Generators I18n"></p>
<p>Ahora que está muy bien pero que si deseas editar el <code>Author</code> directamente dentro del <code>Article</code> como así y que se cree un nuevo <code>Author</code> si no existe y el uso del actual <code>Author</code> si ese nombre existe. Esto es simple.</p>
<h2>Editar / Añadir autor</h2>
<p>Con el fin de añadir la funcionalidad descrita anteriormente tenemos que añadir un poco de código en tres lugares diferentes. En primer lugar necesitas embeber el formulario <code>Author</code> en el formulario <code>Article</code> editando <code>lib/form/doctrine/ArticleForm.class.php</code> y agregue el código siguiente.</p>
<pre>
public function configure()
{
  unset($this['author_id']);
  $authorForm = new AuthorForm($this-&gt;getObject()-&gt;getAuthor());
  unset($authorForm['about']);
  $this-&gt;embedForm('Author', $authorForm);

  $this-&gt;embedI18n(array('en', 'fr'));
}
</pre>
<blockquote class="sidebar"><p class="title">Optionally Optimize Queries</p>
<p>Ahora podemos modificar las acciones de la clase <code>articles</code> para que se le sumen el <code>Autor</code> y la <code>Traducción</code> a fin de que los datos se sumen a la consulta  principal y no perezosamente cargado por Doctrine invocando adicionales consultas a la base de datos. Este paso es opcional. Abre <code>apps/backend/modules/articles/actions/actions.class.php</code> y sobreescribe la función <code>executeEdit()</code>.</p>
<pre>
public function executeEdit(sfWebRequest $request)
{
  $this-&gt;article = Doctrine_Query::create()
    -&gt;from('Article a')
    -&gt;leftJoin('a.Author a2')
    -&gt;leftJoin('a.Translation t')
    -&gt;where('a.id = ?', $request-&gt;getParameter('id'))
    -&gt;fetchOne();
  $this-&gt;form = $this-&gt;configuration-&gt;getForm($this-&gt;article);
}
</pre>
</blockquote>
<p>Ahora, al ver la la edición y la creación de un artículo verá el formulario incorporado para el autor con la información existente.</p>
<p><img src="http://www.symfony-project.org/uploads/assets/doctrine/new_admin_gen_author.gif" alt="New Admin Generators Embedded Author"></p>
<p>Ahora el último paso es decir a Doctrine para que busque objetos existentes de <code>Author</code> la hora de establecer el nombre para que un nombre duplicado de  <code>Author</code> no sea creado. Edita <code>lib/model/doctrine/Author.class.php</code> y sobreescribe el <code>name</code> mutator añadiendo el siguiente código.</p>
<pre>
public function setName($name)
{
  $name = trim($name);
  $found = Doctrine_Query::create()
    -&gt;select('a.id')
    -&gt;from('Author a')
    -&gt;where('a.name = ?', $name)
    -&gt;fetchOne(array(), Doctrine::HYDRATE_ARRAY);
  if ($found)
  {
    $this-&gt;assignIdentifier($found['id']);
  } else {
    $this-&gt;_set('name', $name);
  }
}
</pre>
<p>El código anterior será para verificar si un <code>Author</code> con el nombre pasado ya existe, Si existe se asignará el identificador del registro encontrado de lo contrario es lo que normalmente haría, establecer el nombre para el objeto.</p>
<blockquote class="note"><p>
  Los métodos <code>_set()</code> y <code>_get()</code> deben utilizarse para evitar un bucle infinito cuando se sobrescriben accessors y mutators.</p>
</blockquote>
<p>Wow, lo que realmente acaba de construir todo un backend para gestionar el contenido de un simple sistema de gestión de contenido en menos de una hora? Estamos seguros de que sí. Pruébalo y disfruta el desarrollo de ricas funcionalidad basada en web utilizando symfony y Doctrine.</p>
<p>La presente, es una traducción al castellano realizada por Roberto G. Puentes Diaz,<br />
sobre el artículo <a target="_blank" href="http://www.symfony-project.org/blog/2008/11/07/new-in-symfony-1-2-doctrine-goodies">new-in-symfony-1-2-doctrine-goodies</a> de Jonathan Wage.</p>
<div>
<table>
<tbody>
<tr>
<td>
        <a href="http://creativecommons.org/licenses/by-nc-nd/3.0/deed.es_AR" rel="license" target="_blank"><br />
          <img src="http://i.creativecommons.org/l/by-nc-nd/3.0/80x15.png" style="border-width: 0pt" alt="Creative Commons License" align="left"><br />
        </a>
      </td>
<td>
        Este <span>trabajo</span> esta licenciado bajo una Licencia<br />
        <a href="http://creativecommons.org/licenses/by-nc-nd/3.0/deed.es_AR" rel="license" target="_blank">Creative Commons Atribución-No Comercial-Sin Obras Derivadas 3.0 Unported</a>.
      </td>
</tr>
</tbody>
</table>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.puentesdiaz.com.ar/2008/11/07/symfony-12-bondades-de-doctrine/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Que Feliz que Soy</title>
		<link>http://blog.puentesdiaz.com.ar/2008/11/04/que-feliz-que-soy/</link>
		<comments>http://blog.puentesdiaz.com.ar/2008/11/04/que-feliz-que-soy/#comments</comments>
		<pubDate>Wed, 05 Nov 2008 00:20:30 +0000</pubDate>
		<dc:creator>puentesdiaz</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Sociedad]]></category>
		<category><![CDATA[Software Libre]]></category>

		<guid isPermaLink="false">http://www.puentesdiaz.com.ar/blog/?p=87</guid>
		<description><![CDATA[Argentina Pais Generoso. Hasta cuando te ven la cara debes poner una sonrisa. Desde aqui, un abrazo solidario para aquellos que siguen siendo rehenes, de estos personajes.]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.puentesdiaz.com.ar/files/2008/11/sonrisas.png"><img class="size-medium wp-image-88 alignleft" src="http://www.puentesdiaz.com.ar/blog/wp-content/uploads/2008/11/sonrisas-300x208.png" alt="" width="300" height="208" /></a></p>
<p>Argentina Pais Generoso.<br />
Hasta cuando te ven la cara debes poner una sonrisa.</p>
<p>Desde aqui, un abrazo solidario para aquellos que siguen siendo rehenes, de estos personajes.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.puentesdiaz.com.ar/2008/11/04/que-feliz-que-soy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Eclipse: Escribiendo Código rapido</title>
		<link>http://blog.puentesdiaz.com.ar/2008/10/28/eclipse-escribiendo-codigo-rapido/</link>
		<comments>http://blog.puentesdiaz.com.ar/2008/10/28/eclipse-escribiendo-codigo-rapido/#comments</comments>
		<pubDate>Tue, 28 Oct 2008 13:10:58 +0000</pubDate>
		<dc:creator>puentesdiaz</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Software Libre]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://www.puentesdiaz.com.ar/blog/?p=62</guid>
		<description><![CDATA[Gracias a nuestro aclamado Eclipse PDT, el desarrollo de PHP, nunca fue tan facil. Si bien, gracias a symfony y al autocompletado, se hace todo muy intuitivo. Con Eclipse podemos hacernos nuestros propios atajos de codigo. Menu  &#62; Window &#62; &#8230; <a href="http://blog.puentesdiaz.com.ar/2008/10/28/eclipse-escribiendo-codigo-rapido/">Sigue leyendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Gracias a nuestro aclamado Eclipse PDT, el desarrollo de PHP, nunca fue tan facil.</p>
<p>Si bien, gracias a symfony y al autocompletado, se hace todo muy intuitivo. Con Eclipse podemos hacernos nuestros propios atajos de codigo.</p>
<p>Menu  &gt; Window &gt; Preferences &gt; PHP  &gt; Templates</p>
<p>Nos ofrecera la posibilidad de editar los existentes o de crear uno nuevo. Le damos a NEW y debemos tener algo asi:</p>
<div id="attachment_63" class="wp-caption alignnone" style="width: 310px"><a href="http://blog.puentesdiaz.com.ar/files/2008/10/pdt_templates.jpg"><img class="size-medium wp-image-63" src="http://www.puentesdiaz.com.ar/blog/wp-content/uploads/2008/10/pdt_templates-300x225.jpg" alt="Captura de como crear un template de código PHP en Eclipse PDT" width="300" height="225" /></a><p class="wp-caption-text">Captura de como crear un template de código PHP en Eclipse PDT</p></div>
]]></content:encoded>
			<wfw:commentRss>http://blog.puentesdiaz.com.ar/2008/10/28/eclipse-escribiendo-codigo-rapido/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Generando el Modelo, a mi manera</title>
		<link>http://blog.puentesdiaz.com.ar/2008/10/24/generando-el-modelo-a-mi-manera/</link>
		<comments>http://blog.puentesdiaz.com.ar/2008/10/24/generando-el-modelo-a-mi-manera/#comments</comments>
		<pubDate>Fri, 24 Oct 2008 12:54:10 +0000</pubDate>
		<dc:creator>puentesdiaz</dc:creator>
				<category><![CDATA[Software Libre]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://www.puentesdiaz.com.ar/blog/?p=44</guid>
		<description><![CDATA[(El presente es un ensayo de como ire descubriendo como hacer cada cosa, por lo que tendría modificaciones sucesivas, sin embargo la idea es que lo que leas sirva y funcione) Es quizás muy petulante el título, pero esa es &#8230; <a href="http://blog.puentesdiaz.com.ar/2008/10/24/generando-el-modelo-a-mi-manera/">Sigue leyendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><sub>(El presente es un ensayo de como ire descubriendo como hacer cada cosa, por lo que tendría modificaciones sucesivas, sin embargo la idea es que lo que leas sirva y funcione)</sub></p>
<p>Es quizás muy petulante el título, pero esa es la idea. Osea Generar el Modelo. <img src='http://blog.puentesdiaz.com.ar/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Como seguro ya se darían cuenta, con anteriores artículos y traducciones, estoy estudiando symfony 1.2 para mi proyecto.</p>
<p>Una de las cosas que hice primero fue hacer un ambiente para mis pruebas, con el fin de tener un ámbito para jugar a lo que se me ocurra. Osea que mi schema tiene muchas cosas, pero como es de pruebas &#8230; que va!</p>
<p>Una de las cosas que siempre me gusto es lo del método mágico __toString() de las clases del modelo generado. El poder luego redefinirlo en la clase personalizada, solicitando que devuelva un getXXX() y poder ver el dato de la base en los ABM / CRUD del administrador en lugar de los PrimaryKey, es realmente mas lindo.</p>
<p>Pero tener que redefinir en cada clase, puede ser molesto &#8230;<br />
Vamos, soy de los que se pierden haciendos &#8220;xxxxxx_id&#8221; por todos lados en el modelo &#8230; <img src='http://blog.puentesdiaz.com.ar/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Por lo que tengo que redefinir muchos  __toString() .</p>
<p>Entonces porque no poder en el schema, definir un atributo tostring a true o especificar el nombre del campo a utilizar por el método magico, para que el generador/builder/constructor del modelo lo haga por mi ya desde la BaseClase.php ?</p>
<blockquote><p>Mi instalacion de Symfony 1.2 esta en /Symfony1.2.<br />
Digamos que en otro equipo distinto del que estamos trabajando, hice una descarga por SVN del la versión 1.2, y luego la copie a este DIR.<br />
Imagino que esto no tiene ningun tipo de incidencia.</p></blockquote>
<p>Veamos un poco el schema:</p>
<pre>propel:
   category:
    _attributes:    { phpName: Category, phpToString: Name }
    name:        varchar(255)</pre>
<p>La idea central, es definir un atributo <strong>phpToString</strong> que nos permita definir un texto, en este caso <strong>Name</strong>, y que en este caso tambien hace referencia al campo name declarado en la linea debajo.<br />
La finalidad es lograr que se genere un código / método toString() para esta clase, como el siguiente :</p>
<pre>    /**
     * Magic Method __toString will return the value of some field
     * if you setup the attributes of your schema for this object/table
     */
    public function __toString()
    {
        return $this-&gt;getName();

    }</pre>
<p>Note que por esta razón, puse <strong>Name</strong>, con la N en mayúsculas. Ya vere despues como hacer la transformación camelcase&#8230;<br />
El generador al <strong>$this-&gt;get</strong> le agregará a continuación lo que hallamos definido</p>
<p>Entiendo que iniciamos el script por generar de cada BaseClase.php, desde SfObjectBuilder. A continuación un extracto de como las clases se van heredando, según su definición:</p>
<pre>class SfObjectBuilder extends PHP5ObjectBuilder {

class PHP5ObjectBuilder extends ObjectBuilder {

abstract class ObjectBuilder extends OMBuilder {

abstract class OMBuilder extends DataModelBuilder {</pre>
<p>Hagamos un salto al objeto OMBuilder (<em>/Symfony1.2/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/classes/propel/engine/builder/om/OMBuilder.php</em>)</p>
<pre>	 /**
	 * Builds the PHP source for current class and returns it as a string.
	 *
	 * This is the main entry point and defines a basic structure that classes should follow.
	 * In most cases this method will not need to be overridden by subclasses.  This method
	 * does assume that the output language is PHP code, so it will need to be overridden if
	 * this is not the case.
	 *
	 * @return     string The resulting PHP sourcecode.
	 */
	public function build()
	{
		$this-&gt;validateModel();

		$script = "&lt;" . "?php\n"; // intentional concatenation
		$this-&gt;addIncludes($script);
		$this-&gt;addClassOpen($script);
		$this-&gt;addClassBody($script);
		$this-&gt;addClassClose($script);
		return $script;
	}</pre>
<p>Estos metodo tan interesantes los podemos encontrar implementado en <em>(/Symfony1.2\lib\plugins\sfPropelPlugin\lib\vendor\propel-generator\classes\propel\engine\builder\om\php5\PHP5ObjectBuilder.php)</em> el objeto PHP5ObjectBuilder (use la flechita que esta a la derecha de la barra siguiente para ver los metodos)</p>
<pre>	/**
	 * Adds the include() statements for files that this class depends on or utilizes.
	 * @param      string &amp;$script The script will be modified in this method.
	 */
	protected function addIncludes(&amp;$script)
	{
	} // addIncludes()

	/**
	 * Adds class phpdoc comment and openning of class.
	 * @param      string &amp;$script The script will be modified in this method.
	 */
	protected function addClassOpen(&amp;$script)
	{

		$table = $this-&gt;getTable();
		$tableName = $table-&gt;getName();
		$tableDesc = $table-&gt;getDescription();
		$interface = $this-&gt;getInterface();

		$script .= "
/**
 * Base class that represents a row from the '$tableName' table.
 *
 * $tableDesc
 *";
		if ($this-&gt;getBuildProperty('addTimeStamp')) {
			$now = strftime('%c');
			$script .= "
 * This class was autogenerated by Propel " . $this-&gt;getBuildProperty('version') . " on:
 *
 * $now
 *";
		}
		$script .= "
 * @package    ".$this-&gt;getPackage()."
 */
abstract class ".$this-&gt;getClassname()." extends ".ClassTools::classname($this-&gt;getBaseClass())." ";

		$interface = ClassTools::getInterface($table);
		if ($interface) {
			$script .= " implements " . ClassTools::classname($interface);
		}

		$script .= " {

";
	}

	/**
	 * Specifies the methods that are added as part of the basic OM class.
	 * This can be overridden by subclasses that wish to add more methods.
	 * @see        ObjectBuilder::addClassBody()
	 */
	protected function addClassBody(&amp;$script)
	{
		$script = "\n" . $script;
		$table = $this-&gt;getTable();
		if (!$table-&gt;isAlias()) {
			$this-&gt;addConstants($script);
			$this-&gt;addAttributes($script);
		}

		$this-&gt;addConstructor($script);
		$this-&gt;addApplyDefaultValues($script);

		// NUEVO CODIGO // NEW CODE
		if ($this-&gt;getPhpToString() != false) {
			$this-&gt;addToString($script);
		}

		$this-&gt;addColumnAccessorMethods($script);
		$this-&gt;addColumnMutatorMethods($script);

		$this-&gt;addHasOnlyDefaultValues($script);

		$this-&gt;addHydrate($script);
		$this-&gt;addEnsureConsistency($script);

		$this-&gt;addManipulationMethods($script);
		$this-&gt;addValidationMethods($script);

		if ($this-&gt;isAddGenericAccessors()) {
			$this-&gt;addGetByName($script);
			$this-&gt;addGetByPosition($script);
			$this-&gt;addToArray($script);
		}

		if ($this-&gt;isAddGenericMutators()) {
			$this-&gt;addSetByName($script);
			$this-&gt;addSetByPosition($script);
			$this-&gt;addFromArray($script);
		}

		$this-&gt;addBuildCriteria($script);
		$this-&gt;addBuildPkeyCriteria($script);
		$this-&gt;addGetPrimaryKey($script);
		$this-&gt;addSetPrimaryKey($script);

		$this-&gt;addCopy($script);

		if (!$table-&gt;isAlias()) {
			$this-&gt;addGetPeer($script);
		}

		$this-&gt;addFKMethods($script);
		$this-&gt;addRefFKMethods($script);
		$this-&gt;addClearAllReferences($script);
	}

	/**
	 * Closes class.
	 * @param      string &amp;$script The script will be modified in this method.
	 */
	protected function addClassClose(&amp;$script)
	{
		$script .= "
} // " . $this-&gt;getClassname() . "
";
	}</pre>
<p>Note la nueva porción de código</p>
<pre>		// NUEVO CODIGO // NEW CODE
		if ($this-&gt;getPhpToString() != false) {
			$this-&gt;addToString($script);
		}</pre>
<p>Quien se encarga de analizar el schema sea YML o XML, es la clase sfPropelDatabaseSchema (<em>E:\wamp\apps\symfony\1.2\lib\plugins\sfPropelPlugin\lib\addon\sfPropelDatabaseSchema.class.php</em>)</p>
<p>La Clase Abstracta XMLElement (<em>/Symfony1.2/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/classes/propel/engine/database/model/XMLElement.php</em>) representa a los elementos de un archivo XML. Es el método loadFromXML() quien toma esos <strong>atributos</strong></p>
<pre>	/**
	 * This is the entry point method for loading data from XML.
	 * It calls a setupObject() method that must be implemented by the child class.
	 * @param      array $attributes The attributes for the XML tag.
	 */
	public function loadFromXML($attributes)
	{
		$this-&gt;attributes = array_change_key_case($attributes, CASE_LOWER);
		$this-&gt;setupObject();
	}</pre>
<p>La misma es heredada por otras como Table y Database.</p>
<p>A la clase Table, debemos agregarle estas modificaciones. Es quien hereda de XMLElement e implementa IDMethod.<br />
(<em>/Symfony1.2/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/classes/propel/engine/database/model/Table.php<br />
</em>)</p>
<p>Un atributo $phpToString</p>
<pre>    /**
     * The field name for the magic method __toString().
     *
     * @var        string
     */
    private $phpToString;</pre>
<p>Cargamos los valores al objeto, entre ellos $this-&gt;phpToString</p>
<pre>	/**
	 * Sets up the Rule object based on the attributes that were passed to loadFromXML().
	 * @see        parent::loadFromXML()
	 */
	public function setupObject()
	{
		$this-&gt;name = $this-&gt;getAttribute("name");
		$this-&gt;phpName = $this-&gt;getAttribute("phpName");
		$this-&gt;idMethod = $this-&gt;getAttribute("idMethod", $this-&gt;getDatabase()-&gt;getDefaultIdMethod());
		$this-&gt;allowPkInsert = $this-&gt;booleanValue($this-&gt;getAttribute("allowPkInsert"));

		// retrieves the method for converting from specified name to a PHP name.
		$this-&gt;phpNamingMethod = $this-&gt;getAttribute("phpNamingMethod", $this-&gt;getDatabase()-&gt;getDefaultPhpNamingMethod());

		$this-&gt;skipSql = $this-&gt;booleanValue($this-&gt;getAttribute("skipSql"));
		$this-&gt;readOnly = $this-&gt;booleanValue($this-&gt;getAttribute("readOnly"));

		$this-&gt;phpToString = $this-&gt;getAttribute("phpToString");
		$this-&gt;pkg = $this-&gt;getAttribute("package");
		$this-&gt;abstractValue = $this-&gt;booleanValue($this-&gt;getAttribute("abstract"));
		$this-&gt;baseClass = $this-&gt;getAttribute("baseClass");
		$this-&gt;basePeer = $this-&gt;getAttribute("basePeer");
		$this-&gt;alias = $this-&gt;getAttribute("alias");

		$this-&gt;heavyIndexing = ( $this-&gt;booleanValue($this-&gt;getAttribute("heavyIndexing"))
		|| ("false" !== $this-&gt;getAttribute("heavyIndexing")
		&amp;&amp; $this-&gt;getDatabase()-&gt;isHeavyIndexing() ) );
		$this-&gt;description = $this-&gt;getAttribute("description");
		$this-&gt;enterface = $this-&gt;getAttribute("interface"); // sic ('interface' is reserved word)
		$this-&gt;treeMode = $this-&gt;getAttribute("treeMode");

		$this-&gt;reloadOnInsert = $this-&gt;booleanValue($this-&gt;getAttribute("reloadOnInsert"));
		$this-&gt;reloadOnUpdate = $this-&gt;booleanValue($this-&gt;getAttribute("reloadOnUpdate"));
	}</pre>
<p>Los Getter y Setter</p>
<pre>    /**
     * Get the value of phpToString.
     * @return     value of phpToString.
     */
    public function getPhpToString()
    {
        return $this-&gt;phpToString;
    }

    /**
     * Set the value of phpToString.
     * @param      v  Value to assign to phpToString.
     */
    public function setPhpToString($v)
    {
        $this-&gt;phpToString = $v;
    }</pre>
<p>Y tambien debemos adaptar la clase Database<br />
(<em>/Symfony1.2/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/classes/propel/engine/database/model/Database.php</em>)</p>
<p>Un atributo $phpToString</p>
<pre>	private $phpToString;</pre>
<p>Cargamos los valores al objeto, entre ellos $this-&gt;phpToString</p>
<pre>	/**
	 * Sets up the Database object based on the attributes that were passed to loadFromXML().
	 * @see        parent::loadFromXML()
	 */
	protected function setupObject()
	{
		$this-&gt;name = $this-&gt;getAttribute("name");
		$this-&gt;phpToString = $this-&gt;getAttribute("phpToString");
		$this-&gt;pkg = $this-&gt;getAttribute("package");
		$this-&gt;baseClass = $this-&gt;getAttribute("baseClass");
		$this-&gt;basePeer = $this-&gt;getAttribute("basePeer");
		$this-&gt;defaultIdMethod = $this-&gt;getAttribute("defaultIdMethod", IDMethod::NATIVE);
		$this-&gt;defaultPhpNamingMethod = $this-&gt;getAttribute("defaultPhpNamingMethod", NameGenerator::CONV_METHOD_UNDERSCORE);
		$this-&gt;defaultTranslateMethod = $this-&gt;getAttribute("defaultTranslateMethod", Validator::TRANSLATE_NONE);
		$this-&gt;heavyIndexing = $this-&gt;booleanValue($this-&gt;getAttribute("heavyIndexing"));
	}</pre>
<p>Los Getter y Setter</p>
<pre>    /**
     * Get the value of phpToString.
     * @return     value of phpToString.
     */
    public function getPhpToString()
    {
        return $this-&gt;phpToString;
    }

    /**
     * Set the value of phpToString.
     * @param      v  Value to assign to phpToString.
     */
    public function setPhpToString($v)
    {
        $this-&gt;phpToString = $v;
    }</pre>
<p>Ahora el XML</p>
<pre>	/**
	 * @see        XMLElement::appendXml(DOMNode)
	 */
	public function appendXml(DOMNode $node)
	{
		$doc = ($node instanceof DOMDocument) ? $node : $node-&gt;ownerDocument;

		$dbNode = $node-&gt;appendChild($doc-&gt;createElement('database'));

		$dbNode-&gt;setAttribute('name', $this-&gt;name);

        if ($this-&gt;phpToString) {
            $dbNode-&gt;setAttribute('phpToString', $this-&gt;phpToString);
        }

		if ($this-&gt;pkg) {
			$dbNode-&gt;setAttribute('package', $this-&gt;pkg);
		}

		if ($this-&gt;defaultIdMethod) {
			$dbNode-&gt;setAttribute('defaultIdMethod', $this-&gt;defaultIdMethod);
		}

		if ($this-&gt;baseClass) {
			$dbNode-&gt;setAttribute('baseClass', $this-&gt;baseClass);
		}

		if ($this-&gt;basePeer) {
			$dbNode-&gt;setAttribute('basePeer', $this-&gt;basePeer);
		}

		if ($this-&gt;defaultPhpNamingMethod) {
			$dbNode-&gt;setAttribute('defaultPhpNamingMethod', $this-&gt;defaultPhpNamingMethod);
		}

		if ($this-&gt;defaultTranslateMethod) {
			$dbNode-&gt;setAttribute('defaultTranslateMethod', $this-&gt;defaultTranslateMethod);
		}

		/*

		FIXME - Before we can add support for domains in the schema, we need
		to have a method of the Column that indicates whether the column was mapped
		to a SPECIFIC domain (since Column-&gt;getDomain() will always return a Domain object)

		foreach ($this-&gt;domainMap as $domain) {
		$domain-&gt;appendXml($dbNode);
		}
		*/
		foreach ($this-&gt;vendorInfos as $vi) {
			$vi-&gt;appendXml($dbNode);
		}

		foreach ($this-&gt;tableList as $table) {
			$table-&gt;appendXml($dbNode);
		}

	}</pre>
<p>Con estas dos clases modificadas, estamos en condiciones de usar estos cambios para la clase OMBuilder que hereda de DataModelBuilder. Pero esta ultima clase no sera necesario modificarla. (<em>/Symfony1.2/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/classes/propel/engine/builder/om/OMBuilder.php</em>). Solo hay que :</p>
<pre>    /**
     * Gets the field name for the magic method __toString.
     * @return     string
     */
    public function getPhpToString()
    {
        $phpToString = ($this-&gt;getTable()-&gt;getPhpToString() ? $this-&gt;getTable()-&gt;getPhpToString() : $this-&gt;getDatabase()-&gt;getPhpToString());
        if (!$phpToString) {
            $phpToString = false;
        }
        return $phpToString;
    }</pre>
<p>Como vimos la clase hija de la anterior OMBuilder, es PHP5ObjectBuilder.<br />
(<em>/Symfony1.2/lib/plugins/sfPropelPlugin/lib/vendor/propel-generator/classes/propel/engine/builder/om/php5/PHP5ObjectBuilder.php</em>)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.puentesdiaz.com.ar/2008/10/24/generando-el-modelo-a-mi-manera/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

