<?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>Chuso! &#187; software</title>
	<atom:link href="http://chusete.es/category/software/feed/" rel="self" type="application/rss+xml" />
	<link>http://chusete.es</link>
	<description>A la tercera va la vencida</description>
	<lastBuildDate>Thu, 17 Nov 2011 19:44:13 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Tipos de posts personalizados en WordPress</title>
		<link>http://chusete.es/2011/11/14/tipos-de-posts-personalizados-en-wordpress/</link>
		<comments>http://chusete.es/2011/11/14/tipos-de-posts-personalizados-en-wordpress/#comments</comments>
		<pubDate>Mon, 14 Nov 2011 19:49:30 +0000</pubDate>
		<dc:creator>chusete</dc:creator>
				<category><![CDATA[desarrollo]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[custom posts]]></category>
		<category><![CDATA[taxonomies]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://chusete.es/?p=1243</guid>
		<description><![CDATA[WordPress es una maravilla de software. Nacido en 2003, actualmente es el gestor de contenidos más usado (53.9% de cuota de mercado). La clave de su éxito, en mi opinión, radica en su sencillez de uso, en su versatilidad, en ser un proyecto libre, y sobre todo en su comunidad de usuarios, que crean plugins [...]]]></description>
			<content:encoded><![CDATA[<p>WordPress es una maravilla de software. Nacido en 2003, actualmente es el gestor de contenidos más usado (<a href="http://w3techs.com/technologies/overview/content_management/all">53.9% de cuota de mercado</a>). La clave de su éxito, en mi opinión, radica en su sencillez de uso, en su versatilidad, en ser un proyecto libre, y sobre todo en su comunidad de usuarios, que crean plugins para casi cualquier cosa que podamos imaginar.</p>
<p>¿Pero sabías que se pueden crear <a href="http://codex.wordpress.org/Post_Types">tipos de posts</a> personalizados en los que alojar cualquier tipo de dato que se te ocurra?<br />
<span id="more-1243"></span><br />
Me explico: Por defecto WordPress trae cuatro tipos de posts distintos:</p>
<ol>
<li><strong>Entradas</strong> &#8211; Es el tipo predeterminado, para alojar nuevas entradas tipo blog.</li>
<li><strong>Páginas</strong> &#8211; Las páginas permanentes, fuera de la estructura cronológica de los posts.</li>
<li><strong>Adjuntos</strong>- Corresponde a la página que hay disponible para cada fichero adjunto.</li>
<li><strong>Revisiones</strong> &#8211; Una revisión es una versión antigua de otro documento, o un borrador.</li>
<li><strong>Menús</strong> &#8211; Son los menús de navegación creados desde el panel de control de WordPress. Sí, también es un tipo de post. ¿Sorprendido? <img src='http://chusete.es/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </li>
</ol>
<p>Todos ellos los crea WordPress automáticamente. Pero además de esos, nos permite crear otros nuevos que se adapten mejor a nuestras necesidades. La magia la lleva a cabo la función <a href="http://codex.wordpress.org/Function_Reference/register_post_type">register_post_type()</a>.</p>
<p>Vamos a realizar un ejemplo en el que crearemos un catálogo de discos duros. Cada disco duro tendrá una serie de campos:</p>
<ul>
<li>Nombre</li>
<li>Descripción</li>
<li>Fabricante</li>
<li>Precio</li>
<li>Capacidad</li>
<li>Velocidad de rotación</li>
<li>Imagen</li>
</ul>
<h2>Paso 1 &#8211; Dar de alta el nuevo tipo de post</h2>
<p>Lo primero será crear el nuevo tipo de post. Podremos hacerlo de dos formas: o bien mediante código PHP, o bien desde el panel de control de WordPress.</p>
<h3>Método 1 &#8211; Con código</h3>
<p>Añadimos este código al fichero functions.php de nuestra plantilla:</p>
<pre name="code" class="php">    // Registramos un nuevo tipo de post discos duros
    add_action('init', 'register_dd', 1);
    function register_dd() {
        $labels = array(
            'name' =&gt; _x('Discos duros', 'post type general name'),
            'singular_name' =&gt; _x('Disco duro', 'post type singular name'),
            'add_new' =&gt; _x('Añadir nuevo', 'Disco duro'),
            'add_new_item' =&gt; __('Añadir nuevo disco duro'),
            'edit_item' =&gt; __('Editar disco duro'),
            'new_item' =&gt; __('Nuevo disco duro'),
            'view_item' =&gt; __('Ver disco duro'),
            'search_items' =&gt; __('Buscar discos duros'),
            'not_found' =&gt;  __('No se ha encontrado nada'),
            'not_found_in_trash' =&gt; __('No se ha encontrado nada en la papelera'),
        );
        $args = array(
            'labels' =&gt; $labels,
            'public' =&gt; true,
            'hierarchical' =&gt; false,
            'menu_position' =&gt; 5,
            'has_archive' =&gt; true,
            'query_var' =&gt; true
            'supports' =&gt; array('title','editor','thumbnail'),
            'rewrite' =&gt; array('slug' =&gt; 'disco-duro'),
        );

        register_post_type( 'disco-duro', $args );
    }</pre>
<p>Paso a paso, esto es lo que hacemos:</p>
<ol>
<li>Enganchamos la función &#8220;register_dd()&#8221; al evento &#8220;init&#8221;, dándole alta prioridad (cuanto más bajo, más prioritario).</li>
<li>Definimos la función register_dd():</li>
<ol>
<li>Creamos un array $labels con todas las etiquetas que acompañarán al panel de control de este nuevo tipo de post.</li>
<li>Creamos otro array con todas las opciones:</li>
<ol>
<li>labels &#8211; Por un lado, asignamos las etiquetas.</li>
<li>public &#8211; Le damos visibilidad pública.</li>
<li>hierarchical &#8211; No es un tipo de post jerárquico, donde pueda tener un post padre.</li>
<li>menu_position &#8211; Introduciendo 5 hacemos que se muestre bajo el menú de entradas.</li>
<li>has_archive &#8211; Permitimos acceder al archivo (listado) de discos duros.</li>
<li>query_var &#8211; Indicamos que se podrán hacer consultas atacando a este tipo de post.</li>
<li>supports &#8211; Lista de las funcionalidades que hemos decidido que tenga soporte este tipo de post. En concreto, permitos que tenga un título, una descripción con su editor WYSIWYG, y una imagen de miniatura.</li>
<li>rewrite &#8211; Indicamos el nombre base que tendrán las URLs amigables.</li>
</ol>
<li>Finalmente, damos de alta el tipo de post, al que llamamos &#8216;discoduro&#8217;.</li>
</ol>
</ol>
<p>Si ahora accedemos al panel de control, esto es lo que veremos:</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/10/Añadir-nuevo-disco-duro.png"><img class="aligncenter size-medium wp-image-1244" title="Añadir nuevo disco duro" src="http://chusete.es/wp-content/uploads/2011/10/Añadir-nuevo-disco-duro-300x142.png" alt="" width="300" height="142" /></a></p>
<p>¡Ya tenemos nuestro tipo de post creado! Ha sido fácil, ¿verdad? <img src='http://chusete.es/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<h3>Método 2 &#8211; Sin código</h3>
<p>¿Dije que la comunidad de desarrolladores de WordPress es genial? Existe un plugin que permite hacer todo eso, pero <em>a golpe de ratón</em>. Os presento a <a href="http://wordpress.org/extend/plugins/more-types/">More Types</a>. Mediante formularios web podremos crear y ajustar tanto como queramos nuestros tipos de posts personalizados. Instálatelo y ve a Ajustes &gt; More Types:</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/10/Captura-de-pantalla-2011-10-24-a-las-22.08.31.png"><img class="aligncenter size-medium wp-image-1245" title="More Types" src="http://chusete.es/wp-content/uploads/2011/10/Captura-de-pantalla-2011-10-24-a-las-22.08.31-300x198.png" alt="" width="300" height="198" /></a></p>
<p>Como ves, aparecen tanto los tipos por defecto, como los definidos por el usuario. Vamos a crear un nuevo tipo definido por el usuario pulsando sobre &#8220;Add new Post Type&#8221;. Completamos los siguientes campos:</p>
<ul>
<li><strong>Post type name singular</strong>: Disco duro.</li>
<li><strong>Post type name plural</strong>: Discos duros.</li>
<li><strong>Features</strong>: Marcamos &#8216;Título&#8217;, &#8216;Editor&#8217; y &#8216;Miniatura&#8217;.</li>
</ul>
<div>Desplegamos &#8216;Advanced Settings&#8217;:</div>
<div>
<ul>
<li><strong>Has archive: </strong>Yes<strong>.</strong></li>
<li><strong>Menu position</strong>: 5.</li>
<li><strong>Menu name</strong>: Discos duros.</li>
<li><strong>&#8216;Add new&#8217; text</strong>: Añadir nuevo.</li>
<li><strong>&#8216;Add new item&#8217; text</strong>: Añadir nuevo disco duro.</li>
<li><strong>&#8216;Edit item&#8217; text</strong>: Editar disco duro.</li>
<li><strong>&#8216;New item&#8217; text</strong>: Nuevo disco duro.</li>
<li><strong>&#8216;View item&#8217; text</strong>: Ver disco duro.</li>
<li><strong>&#8216;Search item&#8217; text</strong>: Buscar disco duro.</li>
<li><strong>&#8216;Not found&#8217; text</strong>: No se ha encontrado nada.</li>
<li><strong>&#8216;Not found in Trash&#8217; text</strong>: No se ha encontrado nada en la papelera.</li>
</ul>
<p>Pulsamos sobre &#8216;Save&#8217; y ya lo tenemos. El resultado es el mismo que en el método 1:</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/10/Añadir-nuevo-disco-duro-2.png"><img class="aligncenter size-medium wp-image-1247" title="Añadir nuevo disco duro" src="http://chusete.es/wp-content/uploads/2011/10/Añadir-nuevo-disco-duro-2-300x149.png" alt="" width="300" height="149" /></a></p>
<h2>Paso 2 &#8211; Taxonomías</h2>
<p>La Wikipedia define a la <a href="http://es.wikipedia.org/wiki/Taxonom%C3%ADa">taxonomía</a> como la ciencia de la clasificación; es decir, una forma de agrupar <em>cosas</em>. Lo has usado ya mucho: cada vez que creas una categoría en tus artículos o cuando introduces las etiquetas. Tal como ocurría con los tipos de posts, WordPress trae tres taxonomías creadas de forma predeterminada:</p>
<ol>
<li>Categorías &#8211; Las categorías que ya has usado para clasificar tus artículos.</li>
<li>Etiquetas &#8211; Etiquetas (palabras clave) que añades a cada artículo.</li>
<li>Categoría de enlace &#8211; Las categorías con las que clasificas los enlaces en WordPress.</li>
</ol>
<p>¿Qué taxonomías podemos crear para clasificar los discos duros? Pues unas cuantas <img src='http://chusete.es/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Pero en este ejemplo vamos a crear sólo una: fabricante. Y de nuevo, tal como sucedía al crear los tipos de posts, podemos crearlo o bien con código, o bien utilizando plugins de terceros sin código.</p>
<h3>Método 1 &#8211; Con código</h3>
<p>Podemos crearla mediante código utilizando la función <a href="http://codex.wordpress.org/Function_Reference/register_taxonomy">register_taxonomy()</a>:</p>
<pre name="code" class="php">    // Y creamos un nueva taxonomía para el nuevo tipo de post
    add_action('init', 'register_df', 1);
    function register_df() {
        $labels = array(
            'name' =&gt; _x( 'Fabricantes', 'taxonomy general name' ),
            'singular_name' =&gt; _x( 'fabricante', 'taxonomy singular name' ),
            'search_items' =&gt;  __( 'Buscar fabricantes' ),
            'popular_items' =&gt; __( 'Fabricantes' ),
            'all_items' =&gt; __( 'Todos' ),
            'edit_item' =&gt; __( 'Editar fabricante' ),
            'update_item' =&gt; __( 'Actualizar fabricante' ),
            'add_new_item' =&gt; __( 'Añadir nuevo fabricante' ),
            'new_item_name' =&gt; __( 'Nuevo nombre de fabricante' ),
            'separate_items_with_commas' =&gt; __( 'Separar fabricantes con comas' ),
            'add_or_remove_items' =&gt; __( 'Añadir o borrar fabricantes' ),
            'choose_from_most_used' =&gt; __( 'Elegir de entre los fabricantes más populares' )
        );
        $args = array(
            'hierarchical' =&gt; true,
            'public' =&gt; true,
            'labels' =&gt; $labels,
            'show_ui' =&gt; true,
            'rewrite' =&gt; array( 'slug' =&gt; 'fabricantes' ),
            'query_var' =&gt; true,
		);

        register_taxonomy('fabricantes', 'discosduros', $args);
    }</pre>
<p>Viéndolo paso a paso:</p>
<ol>
<li>Atamos la función &#8216;register_df&#8217;()&#8217; al evento &#8216;init&#8217;, de nuevo con alta prioridad.</li>
<li>Definimos la función register_df():</li>
<ol>
<li>Creamos un array $labels con todas las etiquetas que acompañarán al panel de control de este nuevo tipo de taxonomía.</li>
<li>Creamos otro array con todas las opciones:</li>
<ol>
<li>hierarchical &#8211; Es un tipo de taxonomía jerárquica. Por ejemplo, las categorías son jerárquicas, mientras que las etiquetas no lo son.</li>
<li>public &#8211; Le damos visibilidad pública.</li>
<li>labels &#8211; Por un lado, asignamos las etiquetas.</li>
<li>show_ui &#8211; Indicamos que se mostrará la interfaz de usuario en el panel de control para gestionarlas.</li>
<li>rewrite &#8211; Nos permite redefinir la estructura de las URLs dinámicas con las que se accede a cada fabricante.</li>
<li>query_var &#8211; Permite realizar consultas SQL atacando a esta taxonomía.</li>
</ol>
<li>Finalmente, damos de alta el tipo de taxonomía, a la que llamamos &#8216;fabricantes&#8217;, y la vinculamos al tipo de post &#8216;discosduros&#8217;.</li>
</ol>
</ol>
<div>¿Qué cambio ha supuesto esto? En resumen, tenemos dos. Por un lado, nos aparecerá una nueva cajita en la página de añadir/editar disco duro, donde podremos establecer el fabricante:</div>
<div><a href="http://chusete.es/wp-content/uploads/2011/11/Añadir-nuevo-disco-duro-‹-Demo-—-WordPress.png"><img class="aligncenter size-medium wp-image-1252" title="Añadir nuevo disco duro ‹ Demo — WordPress" src="http://chusete.es/wp-content/uploads/2011/11/Añadir-nuevo-disco-duro-‹-Demo-—-WordPress-300x166.png" alt="" width="300" height="166" /></a></div>
<div>Y por otro, tenemos un nuevo apartado en la columna izquierda desde donde podremos gestionar los fabricantes:</div>
<div><a href="http://chusete.es/wp-content/uploads/2011/11/Fabricantes-‹-Demo-—-WordPress.png"><img class="aligncenter size-medium wp-image-1253" title="Fabricantes ‹ Demo — WordPress" src="http://chusete.es/wp-content/uploads/2011/11/Fabricantes-‹-Demo-—-WordPress-300x166.png" alt="" width="300" height="166" /></a></div>
</div>
<div>
<h3>Método 2 &#8211; Sin código</h3>
</div>
<p>Espera, ¿dije que la comunidad de desarrolladores de WordPress es genial? <img src='http://chusete.es/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  También existe un plugin que nos permita crear taxonomías desde el panel de control. En esta ocasión os presento a <a href="http://wordpress.org/extend/plugins/more-taxonomies/">More Taxonomies</a> (ojo, está en estado beta). Mediante formularios web podremos crear y ajustar tanto como queramos nuestros tipos de taxonomías personalizadas. Instálatelo y ve a Ajustes &gt; More Taxonomies:</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/11/More-Taxonomies-‹-Demo-2-—-WordPress.png"><img class="aligncenter size-medium wp-image-1254" title="More Taxonomies ‹ Demo 2 — WordPress" src="http://chusete.es/wp-content/uploads/2011/11/More-Taxonomies-‹-Demo-2-—-WordPress-300x164.png" alt="" width="300" height="164" /></a></p>
<p>Como ves, al pie aparecen tanto las taxonomías por defecto, como las definidos por el usuario. Vamos a crear una nueva taxonomía definida por el usuario pulsando sobre &#8220;Add new Taxonomie&#8221;. Completamos los siguientes campos:</p>
<ul>
<li><strong>Taxonomy name singular</strong>: Disco duro.</li>
<li><strong>Taxonomy name plural</strong>: Discos duros.</li>
<li><strong>Hierarchical</strong>: Yes</li>
<li><strong>Allow permalinks</strong>: Yes</li>
<li><strong>Taxonomy slug</strong>: fabricante</li>
<li><strong>Show tag cloud</strong>: No</li>
<li><strong>Available to</strong>: Discos duro</li>
</ul>
<div>Desplegamos &#8216;Advanced Settings&#8217;:</div>
<div>
<ul>
<li><strong>Allow queries: </strong>Yes.</li>
<li><strong>Query variable</strong>: fabricante.</li>
<li><strong>&#8216;Search&#8217; label text</strong>: Buscar fabricantes.</li>
<li><strong>&#8216;Popular&#8217; label text</strong>: Fabricantes.</li>
<li><strong>&#8216;All&#8217; label text</strong>: Todos.</li>
<li><strong>&#8216;Edit&#8217; label text</strong>: Editar fabricante.</li>
<li><strong>&#8216;Update&#8217; label text</strong>: Actualizar fabricante.</li>
<li><strong>&#8216;Add new&#8217; label text</strong>: Añadir fabricante.</li>
<li><strong>&#8216;Add new name&#8217; label text</strong>: Nuevo nombre de fabricante.</li>
<li><strong>&#8216;Separate with commas&#8217; label text</strong>: Separar fabricantes con comas.</li>
<li><strong>&#8216;Add or remove item&#8217; label</strong>: Añadir o borrar fabricantes.</li>
<li><strong>&#8216;Choose from most used&#8217; label</strong>: Elegir de entre los fabricantes más populares.</li>
</ul>
<div>Pulsamos sobre &#8216;Save&#8217;, y ya tenemos creada nuestra nueva taxonomía. De nuevo, el resultado es equivalente a realizarlo sin código:</div>
</div>
<div><a href="http://chusete.es/wp-content/uploads/2011/11/Fabricantes-‹-Demo-2-—-WordPress.png"><img class="aligncenter size-medium wp-image-1256" title="Fabricantes ‹ Demo 2 — WordPress" src="http://chusete.es/wp-content/uploads/2011/11/Fabricantes-‹-Demo-2-—-WordPress-300x166.png" alt="" width="300" height="166" /></a></div>
<h2>Paso 3 &#8211; Añadir nuevos campos</h2>
<div>Nuestro nuevo tipo de post ya es capaz de alojar 4 de los 7 campos que queríamos para cada disco duro:</div>
<div>
<ol>
<li>Nombre.</li>
<li>Descripción.</li>
<li>Imagen.</li>
<li>Fabricante.</li>
</ol>
<div>Pero nos quedan otros tres:</div>
<div>
<ol>
<li>Precio.</li>
<li>Capacidad.</li>
<li>Velocidad de rotación.</li>
</ol>
<p>Dado que tanto la capacidad como la velocidad de rotación son cifras más o menos redondas que comparten muchos discos duros entre sí, podríamos haber creado una taxonomía para cada uno de ellos, tal como hemos hecho con los fabricantes. Sin embargo, y dado que se trata de un ejemplo didáctico, vamos a utilizar otro método.</p>
<p>Seguramente ya sepas que WordPress permite añadir campos personalizados a cada post (incluso en las entradas normales tipo blog). Puedes conocer mucho más sobre ellos en el apartado &#8216;<a href="http://codex.wordpress.org/Custom_Fields">Custom Fields</a>&#8216; de la documentación de WordPress. Su funcionamiento es muy sencillo: Cuando estés editando un post, activa la vista de los campos personalizados. Pulsa sobre &#8216;Opciones de pantalla&#8217; y activa el checkbox &#8216;Campos personalizados&#8217;. Ahora, al pie del formulario te aparecerá un nuevo apartado para gestionar los campos personalizados:</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/11/Captura-de-pantalla-2011-11-14-a-las-14.28.17.png"><img class="aligncenter size-medium wp-image-1257" title="Captura de pantalla 2011-11-14 a la(s) 14.28.17" src="http://chusete.es/wp-content/uploads/2011/11/Captura-de-pantalla-2011-11-14-a-las-14.28.17-300x95.png" alt="" width="300" height="95" /></a></p>
<p>Su funcionamiento es de tipo clave-valor. Es decir, introduces un nombre, que será el nombre con el que más adelante podrás acceder al campo personalizados, y finalmente escribes el valor que contiene la <em>variable</em>.</p>
<p>Por ejemplo, podríamos crear el campo &#8216;size&#8217;, donde especificar el tamaño de cada disco duro. En ese caso, pondríamos:</p>
<ul>
<li>Nombre: size</li>
<li>Valor: el tamaño, por ejemplo 1TB.</li>
</ul>
<p>Y pulsamos sobre &#8216;Añadir un campo personalizado&#8217;.</p>
<p>Todo esto funciona muy bien, pero ¿y si nos confundimos al escribir el nombre del campo? ¿Y si no lo recordamos? ¿O si se nos olvida introducir un campo? A diferencia de los dos pasos anteriores, esta vez creo que es muy recomendable crear nuestros nuevos tipos de datos mediante plugins. Es decir, de nuevo, ¡la comunidad de WordPress sale al rescate! Si ya os he presentado <strong>More Types</strong> y <strong>More Taxonomies</strong>, ¿sabéis quién queda? Os presento a <a href="http://wordpress.org/extend/plugins/more-fields/">More Fields</a>.</p>
<p>Con More Fields podremos crear campos personalizados de cualquier tipo (radio, checkbox, text, textarea, select, etc.), adjuntos a cualquiera de los tipos de post. En concreto vamos a crear nuestros tres campos (precio, capacidad, velocidad de rotación) a nuestro tipo de post personalizado (discos duros).</p>
<p>Una vez que lo hemos instalado, vamos a Ajustes &gt; More Fields, y creamos un nuevo bloque de campos (caja donde ubicaremos los nuevos campos) llamado &#8216;Características&#8217;, vinculado al tipo de post &#8216;Disco duro&#8217;, y pulsamos sobre &#8216;Save&#8217;:</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/11/Captura-de-pantalla-2011-11-14-a-las-15.21.28.png"><img class="aligncenter size-medium wp-image-1259" title="Captura de pantalla 2011-11-14 a la(s) 15.21.28" src="http://chusete.es/wp-content/uploads/2011/11/Captura-de-pantalla-2011-11-14-a-las-15.21.28-300x128.png" alt="" width="300" height="128" /></a>Ya creado, accedemos a nuestro nuevo bloque y pulsamos sobre &#8216;Add new Field&#8217; para cada uno de los campos.</p>
<h3>Precio</h3>
<p>Introducimos estos valores:</p>
<ul>
<li><strong>Field title</strong> &#8211; Corresponde al título que aparecerá junto al campo: <em>Precio</em>.</li>
<li><strong>Custom field key</strong> &#8211; Nombre que tendrá la clave cuando queramos acceder al campo desde la plantilla: <em>price</em>.</li>
<li><strong>Caption</strong> &#8211; Texto con instrucciones junto al campo: <em>Introduzca el precio en Euros</em>.</li>
<li><strong>Field type</strong> &#8211; Number</li>
</ul>
<div>Y pulsamos sobre &#8216;Save&#8217;.</div>
<h3></h3>
<h3>Capacidad</h3>
<p>Introducimos estos valores:</p>
<ul>
<li><strong>Field title</strong> - <em>Capacidad</em>.</li>
<li><strong>Custom field key</strong> - <em>size</em>.</li>
<li><strong>Caption</strong> - <em>Introduzca la capacidad del disco duro en GigaBytes.</em></li>
<li><strong>Field type</strong> - Number</li>
</ul>
<div>Y pulsamos sobre &#8216;Save&#8217;.</div>
<div>
<h3></h3>
<h3>Velocidad de rotación</h3>
<p>Introducimos estos valores:</p>
<ul>
<li><strong>Field title</strong> - <em>Velocidad de rotación</em>.</li>
<li><strong>Custom field key</strong> - <em>speed</em>.</li>
<li><strong>Caption</strong> - <em>Seleccione la velocidad de rotación en revoluciones por minuto.</em></li>
<li><strong>Field type</strong> - Select.</li>
<li><strong>Values</strong> - 15000, 10000, 7200, 5400, 4800.</li>
</ul>
<p>Y pulsamos sobre &#8216;Save&#8217;.</p>
</div>
<p>¡Y ya tenemos creados los tres campos que nos faltaban! Si ahora accedemos al formulario de añadir o editar disco duro, veremos esto:</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/11/Captura-de-pantalla-2011-11-14-a-las-15.36.43.png"><img class="aligncenter size-medium wp-image-1260" title="Captura de pantalla 2011-11-14 a la(s) 15.36.43" src="http://chusete.es/wp-content/uploads/2011/11/Captura-de-pantalla-2011-11-14-a-las-15.36.43-300x110.png" alt="" width="300" height="110" /></a>Ya tenemos nuestro nuevo tipo de post creado al completo: Podemos crear nuevos discos duros, gestionar sus fabricantes, su imagen destacada, su título y descripción, y añadir las características técnicas del mismo. Mola, ¿verdad? <img src='http://chusete.es/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h2>Paso 4 &#8211; Mejorando el panel de discos duros</h2>
<p>Este paso no es estrictramente necesario, pero puede mejorar notablemente la experiencia de uso a la hora de trabajar con nuestros tipos de post personalizados. Vamos a hacer que el panel de control de discos duros sea mucho más amigable. Vamos a pasar de este panel:</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/11/Captura-de-pantalla-2011-11-14-a-las-16.16.45.png"><img class="aligncenter size-medium wp-image-1261" title="Captura de pantalla 2011-11-14 a la(s) 16.16.45" src="http://chusete.es/wp-content/uploads/2011/11/Captura-de-pantalla-2011-11-14-a-las-16.16.45-300x66.png" alt="" width="300" height="66" /></a>a este otro:</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/11/Captura-de-pantalla-2011-11-14-a-las-16.17.33.png"><img class="aligncenter size-medium wp-image-1262" title="Captura de pantalla 2011-11-14 a la(s) 16.17.33" src="http://chusete.es/wp-content/uploads/2011/11/Captura-de-pantalla-2011-11-14-a-las-16.17.33-300x64.png" alt="" width="300" height="64" /></a>mucho más adaptado a nuestras necesidades, con más columnas, todas ellas ordenables, y con nuevos filtros en función del fabricante. Estos códigos están extraídos de la <a href="http://yoast.com/custom-post-type-snippets/">web de Yoast</a>. Simplemente copiamos y pegamos estos bloques de código al funcions.php de nuestra plantilla:</p>
<h3>Añadiendo nuevas columnas</h3>
<pre name="code" class="php">function change_columns( $cols ) {
  $cols = array(
    'cb'            =&gt; '&lt;input type="checkbox" /&gt;',
    'title'         =&gt; __( 'Nombre', 'trans'),
    'manufacturer'  =&gt; __( 'Fabricante',      'trans' ),
    'size'          =&gt; __( 'Capacidad', 'trans' ),
    'price'         =&gt; __( 'Precio', 'trans' ),
  );
  return $cols;
}
add_filter( "manage_disco-duro_posts_columns", "change_columns" );

// Definir contenido de las columnas no estándar
function custom_columns( $column, $post_id ) {
  switch ( $column ) {
    case "manufacturer":
      $manufacturers = get_the_terms($post_id, 'fabricante');
      foreach($manufacturers as $item) {
        echo '&lt;a href="/'.$item-&gt;taxonomy."/".$item-&gt;slug.'"&gt;'.$item-&gt;name."&lt;/a&gt;";
        break;
      }
      break;
    case "size":
      echo get_post_meta( $post_id, 'size', true)." GB";
      break;
    case "price":
      echo get_post_meta( $post_id, 'price', true)." €";
      break;
  }
}
add_action( "manage_disco-duro_posts_custom_column", "custom_columns", 10, 2 );</pre>
<h3>Haciendo las columnas ordenables</h3>
<pre name="code" class="php">function sortable_columns() {
  return array(
    'title' =&gt; 'title',
    'manufacturer'      =&gt; 'manufacturer',
    'size' =&gt; 'size',
    'price'     =&gt; 'price'
  );
}
add_filter( "manage_edit-disco-duro_sortable_columns", "sortable_columns" );</pre>
<h3>Añadir filtros para las taxonomías</h3>
<pre name="code" class="php">function taxonomy_filter_restrict_manage_posts() {
    global $typenow;

    if ( $typenow == 'disco-duro' ) {
    	$filters = get_object_taxonomies( $typenow );

        foreach ( $filters as $tax_slug ) {
            $tax_obj = get_taxonomy( $tax_slug );
            wp_dropdown_categories( array(
                'show_option_all' =&gt; __('Mostrar todos los '.$tax_obj-&gt;label ),
                'taxonomy' 	  =&gt; $tax_slug,
                'name' 		  =&gt; $tax_obj-&gt;name,
                'orderby' 	  =&gt; 'name',
                'selected' 	  =&gt; $_GET[$tax_slug],
                'hierarchical' 	  =&gt; $tax_obj-&gt;hierarchical,
                'show_count' 	  =&gt; false,
                'hide_empty' 	  =&gt; true
            ) );
        }
    }
}
add_action( 'restrict_manage_posts', 'taxonomy_filter_restrict_manage_posts' );

function taxonomy_filter_post_type_request( $query ) {
  global $pagenow, $typenow;

  if ( 'edit.php' == $pagenow ) {
    $filters = get_object_taxonomies( $typenow );
    foreach ( $filters as $tax_slug ) {
      $var = &amp;$query-&gt;query_vars[$tax_slug];
      if ( isset( $var ) ) {
        $term = get_term_by( 'id', $var, $tax_slug );
        $var = $term-&gt;slug;
      }
    }
  }
}
add_filter( 'parse_query', 'taxonomy_filter_post_type_request' );</pre>
<p>¡Y ya tenemos nuestro panel de control personalizado para nuestro tipo de dato personalizado!</p>
<h2>Paso 5 &#8211; Plantillas</h2>
<p>Supongo que estarás familiarizado con el desarrollo de plantillas en WordPress. Por si acaso no lo estás, te recomiendo revisar la <a href="http://codex.wordpress.org/Template_Hierarchy">jerarquía de plantillas</a>, para saber cuáles tenemos que definir. En concreto podríamos definir estas:</p>
<ul>
<li>Lista de discos duros.</li>
<li>Vista de un disco duro.</li>
<li>Lista de fabricantes de discos duros.</li>
<li>Vista de un fabricante de discos duros.</li>
</ul>
<div>¿Cómo sabemos qué ficheros debemos editar o crear? Si revisamos el diagrama de la jerarquía de plantillas de WordPress, lo veremos muy claro:</div>
<h3><img class="alignnone aligncenter" src="http://codex.wordpress.org/images/1/18/Template_Hierarchy.png" alt="" width="100%" /></h3>
<p>Pero antes de nada; vamos a asegurarnos de que ya podemos acceder a las páginas de nuestros discos duros, y al listado. Da de alta un nuevo elemento de tipo disco duro y, una vez guardado, pulsa sobre &#8220;Ver disco duro&#8221;. Te llevará a una URL similar a www.example.com/disco-duro/nombre-del-disco-duro. Si te fijas en el diagrama, verás que se está utilizando el fichero de plantilla single.php. Del mismo modo, para acceder a la lista de discos duros (www.example.com/disco-duro/) se utiliza el fichero por defecto archive.php.</p>
<div class="note">
<h3>¿Errores 404?</h3>
<p>Si te sale un error 404 &#8211; página no encontrada, prueba a ir a Ajustes &gt; Enlaces permanentes &gt; Guardar. Es simplemente para refrescar la configuración de reescritura de URLs.</p>
</div>
<h3><span class="Apple-style-span" style="font-size: 13px; font-weight: normal;">Ahora si, por ejemplo, quisiéramos editar la vista de un disco duro, editaríamos single-disco-duro.php. Un buen punto de partida suele ser copiar y pegar el contenido del fichero single.php para después adaptarlo a las nuevas necesidades. Por ejemplo, así podría quedarte:</span></h3>
<pre name="code" class="php">&lt;?php get_header(); ?&gt;

&lt;?php if ( have_posts() ) while ( have_posts() ) : the_post(); ?&gt;
    &lt;?php $manufacturers = get_the_terms(get_the_ID(), 'fabricante');?&gt;
	&lt;?php $custom = get_post_custom(); ?&gt;
	&lt;h1 class="entry-title"&gt;&lt;?php the_title(); ?&gt;&lt;/h1&gt;
    &lt;?php
    if ( has_post_thumbnail() ) {
      the_post_thumbnail();
    }
    ?&gt;
	&lt;h2&gt;Fabricante: &lt;?php foreach($manufacturers as $item) { echo $item-&gt;name; break; } ?&gt;&lt;/h2&gt;
    &lt;?php the_content(); ?&gt;
    &lt;p&gt;
        Precio: &lt;?php echo $custom['price'][0]; ?&gt;€&lt;br /&gt;
        Capacidad: &lt;?php echo $custom['size'][0]; ?&gt;GB&lt;br /&gt;
        Velocidad: &lt;?php echo $custom['speed'][0]; ?&gt; rpm&lt;br /&gt;
    &lt;/p&gt;
&lt;?php endwhile; // end of the loop. ?&gt;

&lt;?php get_sidebar(); ?&gt;
&lt;?php get_footer(); ?&gt;</pre>
<p>Y procederíamos de igual manera para editar las vistas de categorías o del listado de discos duros (archive-disco-duro.php).</p>
<p>Pero un momento&#8230; Nos hemos saltado la explicación de cómo utilizar en nuestras plantillas los valores de los campos personalizados. En general, para utilizar estos valores, tenemos cuatro funciones disponibles:</p>
<ol>
<li><a href="http://codex.wordpress.org/Function_Reference/get_post_custom">get_post_custom()</a> &#8211; Devuelve un array que, para cada clave (cada campo personalizado) contiene otro array con todos los valores que se le han asignado.</li>
<li><a href="http://codex.wordpress.org/Function_Reference/get_post_custom_values">get_post_custom_values()</a> &#8211; Útil para cuando un campo personalizado tiene más de un valor. Devuelve un array con todos los valores que se le ha asignado.</li>
<li><a href="http://codex.wordpress.org/Function_Reference/get_post_custom_keys">get_post_custom_keys()</a> &#8211; Devuelve un array con los nombres de claves (campos personalizados) que hay en uso en un determinado post.</li>
<li><a href="http://codex.wordpress.org/Function_Reference/get_post_meta">get_post_meta()</a> &#8211; Devuelve el valor de los campos personalizados que tengan el nombre indicado.</li>
</ol>
<p>¡Y esto es todo! Con un poco de suerte, todo esto te será de tanta utilidad como a mí a la hora de desarrollar nuevas páginas en WordPress. Ya no estás limitado a Páginas y a Entradas. Y lo mejor de todo: se puede hacer casi sin tocar una línea de código.</p>
</div>
</div>
<div class="tweetmeme_button" style="float: left; margin-right: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fchusete.es%2F2011%2F11%2F14%2Ftipos-de-posts-personalizados-en-wordpress%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fchusete.es%2F2011%2F11%2F14%2Ftipos-de-posts-personalizados-en-wordpress%2F&amp;source=chuso&amp;style=normal&amp;service=bit.ly&amp;service_api=R_86054639b9f90148987197dfdc061697&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
]]></content:encoded>
			<wfw:commentRss>http://chusete.es/2011/11/14/tipos-de-posts-personalizados-en-wordpress/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rutas en bici + Android</title>
		<link>http://chusete.es/2011/04/10/rutas-en-bici-android/</link>
		<comments>http://chusete.es/2011/04/10/rutas-en-bici-android/#comments</comments>
		<pubDate>Sun, 10 Apr 2011 15:55:20 +0000</pubDate>
		<dc:creator>chusete</dc:creator>
				<category><![CDATA[software]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[bicicleta]]></category>
		<category><![CDATA[endomondo]]></category>
		<category><![CDATA[mapas]]></category>
		<category><![CDATA[rutas]]></category>

		<guid isPermaLink="false">http://chusete.es/?p=1020</guid>
		<description><![CDATA[Hola Ahora que parece que el buen tiempo ha llegado para quedarse, es el momento de volver a coger la bici. Aprovechando mi nuevo teléfono, tengo la oportunidad de poder llevar un perfecto seguimiento de las rutas que hago. Añadir rutas Memorizar todos los caminos puede ser un poco complicado. Pero por suerte estos teléfonos [...]]]></description>
			<content:encoded><![CDATA[<p>Hola <img src='http://chusete.es/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Ahora que parece que el buen tiempo ha llegado para quedarse, es el momento de volver a coger la bici. Aprovechando mi <a href="http://www.samsung.com/global/microsite/galaxys/">nuevo teléfono</a>, tengo la oportunidad de poder llevar un perfecto seguimiento de las rutas que hago.</p>
<h2>Añadir rutas</h2>
<p>Memorizar todos los caminos puede ser un poco complicado. Pero por suerte estos teléfonos traen GPS integrado. ¿Cómo podemos importar previamente nuestras rutas? Con Google Maps es muy sencillo. En primer lugar, definimos cómodamente la ruta en Google Earth desde nuestro PC:</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/04/add-route.png"><img src="http://chusete.es/wp-content/uploads/2011/04/add-route.png" alt="" title="add route" width="264" height="52" class="size-full wp-image-1021" /></a></p>
<p>Una vez definida la ruta, la guardamos a un fichero .kmz, pulsando sobre &#8220;Guardar lugar como&#8230;&#8221;</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/04/Captura-de-pantalla-2011-04-10-a-las-17.33.56.png"><img src="http://chusete.es/wp-content/uploads/2011/04/Captura-de-pantalla-2011-04-10-a-las-17.33.56-300x187.png" alt="" title="Guardar ruta a fichero .kmz" width="300" height="187" class="size-medium wp-image-1022" /></a></p>
<p>Ahora, desde <a href="http://maps.google.es/">Google Maps</a>, y habiendo iniciado sesión con nuestra cuenta de Google, accedemos a &#8220;Mis mapas&#8221; > &#8220;Crear un mapa nuevo&#8221; > &#8220;Importar&#8221;, y seleccionamos el fichero .kmz. Establecemos un título y listo, ya tenemos la ruta lista para consultar en cualquier momento.</p>
<p>Ya desde Android, accedemos a Maps, pulsamos sobre el botón &#8220;Capas&#8221;, y desde ahí en &#8220;Más capas&#8221; > &#8220;Mis mapas&#8221;, podremos seleccionar cualquiera de nuestras rutas. ¡Y ya está! <img src='http://chusete.es/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  De esta forma ya no te perderás por los caminos.</p>
<h2>Seguimientos</h2>
<p>Existen muchas aplicaciones que realizan un seguimiento de los recorridos. Yo utilizo <a href="http://www.endomondo.com/home">Endomondo</a>, y me funciona de maravilla. De nuevo, mediante GPS, realiza un completo seguimiento del recorrido, velocidades, tiempos, realiza pausas automáticas, guarda un histórico, calorías quemadas, etc. Lo arrancas, y no es necesario que vuelvas a preocuparte hasta que finalices la ruta <img src='http://chusete.es/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Por supuesto, sirve igualmente para recorridos a pie.</p>
<p>Destacaría de esta plataforma, respecto a otras, su facilidad de uso, la gran comunidad de usuarios que hay detrás, que es multiplataforma (Symbian, Android, iOs, Blackberry), altamente social y gratuito (pese a que existe una versión de pago por 2.95€).</p>
<p>Ahora que la batería de mi teléfono está cargada, me retiro. ¡Me espera una pequeña ruta de 20Km!</p>
<p><em><strong>Edit. 10/04/2011 a las 19:48.</strong></em><br />
Soy un lila; hacía bastante viento (rachas de 45km/h), de modo que al final no he llegado a los 20Km. Pero como muestra de la utilidad de &#8220;compartir rutas&#8221; de Endomondo, <a href="http://www.endomondo.com/workouts/jc64EA7HuRw">aquí está mi práctica de hoy</a>:</p>
<p><iframe src="http://www.endomondo.com/embed/workouts?w=jc64EA7HuRw&#038;width=450&#038;height=600" width="450" height="600" frameborder="0" scrolling="no"></iframe></p>
<p>Y aquí las rachas de viento registradas hoy en el observatorio de Toledo:</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/04/Captura-de-pantalla-2011-04-10-a-las-19.53.06.png"><img src="http://chusete.es/wp-content/uploads/2011/04/Captura-de-pantalla-2011-04-10-a-las-19.53.06.png" alt="" title="Rachas de viento en Toledo el 10/04/2011" width="450" class="size-full wp-image-1031" /></a></p>
<div class="tweetmeme_button" style="float: left; margin-right: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fchusete.es%2F2011%2F04%2F10%2Frutas-en-bici-android%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fchusete.es%2F2011%2F04%2F10%2Frutas-en-bici-android%2F&amp;source=chuso&amp;style=normal&amp;service=bit.ly&amp;service_api=R_86054639b9f90148987197dfdc061697&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
]]></content:encoded>
			<wfw:commentRss>http://chusete.es/2011/04/10/rutas-en-bici-android/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Introducción a Doctrine 2</title>
		<link>http://chusete.es/2011/02/19/introduccion-a-doctrine-2/</link>
		<comments>http://chusete.es/2011/02/19/introduccion-a-doctrine-2/#comments</comments>
		<pubDate>Sat, 19 Feb 2011 02:38:32 +0000</pubDate>
		<dc:creator>chusete</dc:creator>
				<category><![CDATA[bases de datos]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[doctrine]]></category>
		<category><![CDATA[doctrine 2]]></category>
		<category><![CDATA[orm]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://chusete.es/?p=978</guid>
		<description><![CDATA[¡Hola! Últimamente sigo liado sumergiéndome en el mundo de ASP.NET, de ADO.NET, y sacando tiempo de debajo de las piedras para un pequeño proyecto en mi querido Zend Framework en PHP. Tras ver ADO.NET Entity Framework sentí la necesidad de usar algo igual en PHP; la solución se llama Doctrine La primera pregunta que nos [...]]]></description>
			<content:encoded><![CDATA[<p>¡Hola! Últimamente sigo liado sumergiéndome en el mundo de ASP.NET, de ADO.NET, y sacando tiempo de debajo de las piedras para un pequeño proyecto en mi querido Zend Framework en PHP. Tras ver ADO.NET Entity Framework sentí la necesidad de usar algo igual en PHP; la solución se llama <a href="http://www.doctrine-project.org/">Doctrine</a> <img src='http://chusete.es/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  La primera pregunta que nos deberíamos hacer es, qué es exactamente Doctrine. Respuesta rápida: Es un <a href="http://en.wikipedia.org/wiki/Object-relational_mapping">ORM</a> de PHP. Pero analicémoslo un poco más.</p>
<p>En primer lugar, ¿qué diantres es un ORM? Viene de las siglas Object-relational mapping, que viene a traducirse como Mapeo objeto-relacional. En concreto es una técnica, o patrón arquitectónico, que permite comunicar dos sistemas distintos, típicamente una base de datos relacional con objetos de un lenguaje orientado a objetos, mediante un sistema que &#8220;mapea&#8221; (vincula) ambos sistemas. Mucha gente (yo mismo) ha creado a mano sus objetos mapeadores que, junto con objetos usando el patrón Active Record, daban un resultado muy similar a lo que un ORM nos ofrece. Pero oye, un ORM hace todo el trabajo sucio por nosotros <img src='http://chusete.es/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Existen ORMs para la mayoría de lenguajes de programación. Por ejemplo, en Java es muy popular <a href="http://www.hibernate.org/">Hibernate</a>, en .NET se utiliza <a href="http://msdn.microsoft.com/en-us/data/ef.aspx">ADO.NET Entity Framework</a>, y en PHP el más usado es Doctrine (<a href="http://cakephp.org/">hay</a> <a href="http://www.propelorm.org/">más</a>). Doctrine está inspirado en Hibernate.</p>
<p>Pero veamos algunas de las características que nos ofrece un ORM como Doctrine 2:</p>
<ul>
<li>Muy sencillo de configurar. De hecho, no es necesario mantener complejos ficheros de configuración XML.</li>
<li>Tiene su propio dialecto de SQL, llamado DQL (Doctrine Query Language).</li>
<li>Puede generar los modelos (las clases PHP que representan una fila de la BD) a partir de la base de datos. Sólo habría que definir las dependencias entre ellos</li>
<li>Del mismo modo, también puede generar la base de datos a partir de los modelos.</li>
</ul>
<p>¡Fantástico! Él puede crear las tablas, y las consultas por nosotros. Pero veamos ahora lo sencillo que es usarlo:</p>
<pre class="php" name="code">
/* Código de inicialización ... */
$user = new User();
$user->name = "john";
$user->password = "doe";
$em->persist($user);
$em->flush();
</pre>
<p>Para que este código funcione sólo tenemos que hacer dos cosas:</p>
<ol>
<li>Creamos el código de inicialización que cree el EntityManager $em. Es el objeto que en última instancia lleva a cabo las acciones.</li>
<li>Definimos las entidades (módulos) especificando en comentarios (o en XML o en YAML) cómo se relaciona con la base de dato</li>
</ol>
<p>Vamos a ver cómo instalarlo y después haremos un ejemplo sencillo en SQLite.</p>
<h2>Instalación</h2>
<p>Si bien podemos instalarlo a mano <a href="http://www.doctrine-project.org/projects/orm/download">descargándolo desde la página de Doctrine</a>, para esta guía asumiré que se ha instalado con PEAR. Para ello tenemos primer que instalar el canal:</p>
<pre>sudo pear channel-discover pear.doctrine-project.org</pre>
<p>Y después instalamos el ORM:</p>
<pre>sudo pear install pear.doctrine-project.org/DoctrineORM-2.0.1</pre>
<p>Ahora lo tenemos instalado. Podemos probar a ejecutar su utilidad de línea de comandos, y nos mostrará esto:</p>
<pre style="overflow: auto; background-color: #f5f5f5; padding: 10px;">$ doctrine
Doctrine Command Line Interface version 2.0.1
Usage:
[options] command [arguments]
Options:
--help           -h Display this help message.
--quiet          -q Do not output any message.
--verbose        -v Increase verbosity of messages.
--version        -V Display this program version.
--ansi           -a Force ANSI output.
--no-interaction -n Do not ask any interactive question.
Available commands:
help                         Displays help for a command (?)
list                         Lists commands
dbal
:import                      Import SQL file(s) directly to Database.
:run-sql                     Executes arbitrary SQL directly from the command line.
orm
:convert-d1-schema           Converts Doctrine 1.X schema into a Doctrine 2.X schema.
:convert-mapping             Convert mapping information between supported formats.
:ensure-production-settings  Verify that Doctrine is properly configured for a production environment.
:generate-entities           Generate entity classes and method stubs from your mapping information.
:generate-proxies            Generates proxy classes for entity classes.
:generate-repositories       Generate repository classes from your mapping information.
:run-dql                     Executes arbitrary DQL directly from the command line.
:validate-schema             Validate that the mapping files.
orm:clear-cache
:metadata                    Clear all metadata cache of the various cache drivers.
:query                       Clear all query cache of the various cache drivers.
:result                      Clear result cache of the various cache drivers.
orm:schema-tool
:create                      Processes the schema and either create it directly on EntityManager Storage Connection or generate the SQL output.
:drop                        Drop the complete database schema of EntityManager Storage Connection or generate the corresponding SQL output.
:update                      Processes the schema and either update the database schema of EntityManager Storage Connection or generate the SQL output.</pre>
<h2>Demo básica</h2>
<p>Para este apartado, voy a utilizar una demo Sandbox (entorno de pruebas) prácticamente igual que la que usan en la <a href="http://www.doctrine-project.org/docs/orm/2.0/en/reference/introduction.html#sandbox-quickstart">documentación de Doctrine 2</a>. En este artículo encontrarás el código de todos los ficheros necesarios. Además, al final del mismo encontrarás un enlace para poder descargarlo.</p>
<p>El proyecto consiste de sólo 4 ficheros:</p>
<ul>
<li>Entities/Users.php &#8211; Modelo de usuarios</li>
<li>Entities/Address.php &#8211; Modelo de dirección</li>
<li>cli-config.php &#8211; Fichero PHP que contiene el código de inicialización necesario para usar la utilidad en linea de comandos &#8216;doctrine&#8217;. <strong>Cada vez que usemos la utilidad &#8216;doctrine&#8217;, tendremos que tener este fichero</strong>.</li>
<li>index.php &#8211; Código de inicialización típico de una aplicación web que utilice Doctrine 2.</li>
</ul>
<p>Vamos a echar un vistazo a los ficheros. En primer lugar veamos cómo es el archivo cli-config.php:</p>
<pre class="php" name="code">&lt;?php
// (1) Autocargamos clases
require_once 'Doctrine/Common/ClassLoader.php';
$classLoader = new \Doctrine\Common\ClassLoader('Doctrine');
$classLoader-&gt;register();
$classLoader = new \Doctrine\Common\ClassLoader('Entities', __DIR__);
$classLoader-&gt;register();
$classLoader = new \Doctrine\Common\ClassLoader('Proxies', __DIR__);
$classLoader-&gt;register();

// (2) Configuración
$config = new \Doctrine\ORM\Configuration();

// (3) Caché
$cache = new \Doctrine\Common\Cache\ArrayCache();
$config-&gt;setMetadataCacheImpl($cache);
$config-&gt;setQueryCacheImpl($cache);

// (4) Driver
$driverImpl = $config-&gt;newDefaultAnnotationDriver(array(__DIR__."/Entities"));
$config-&gt;setMetadataDriverImpl($driverImpl);

// (5) Proxies
$config-&gt;setProxyDir(__DIR__ . '/Proxies');
$config-&gt;setProxyNamespace('Proxies');

// (6) Conexión
$connectionOptions = array(
'driver' =&gt; 'pdo_sqlite',
'path' =&gt; 'database.sqlite'
);

// (7) EntityManager
$em = \Doctrine\ORM\EntityManager::create($connectionOptions, $config);

// (8) HelperSet
$helperSet = new \Symfony\Component\Console\Helper\HelperSet(array(
'db' =&gt; new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($em-&gt;getConnection()),
'em' =&gt; new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em)
));</pre>
<p>¡Que nadie se asuste! Realmente es un código muy sencillo, y prácticamente siempre se usará algo igual o muy parecido. Para superar el medio inicial, vamos a ver detalladamente qué es lo que ha pasado. El proceso de inicialización consta básicamente de dos pasos: Por una parte hay que asegurarse de que las clases de Doctrine pueden cargarse, y por otra hay que crear una instancia del Entity Manager. Siguiendo paso a paso:</p>
<ol>
<li>En primer lugar <strong>autocargamos las clases necesaria</strong>s (nota: para esto podríamos haber utilizado el autocargador de otro framework). En concreto autocargaremos 3 secciones:
<ol>
<li>El propio Doctrine, que trae Common, DBAL, ORM y Symfony. Si lo hemos instalado con PEAR, podremos verlo en el directorio /usr/share/php/Doctrine.</li>
<li>Entities, que es el directorio en el que almacenaremos nuestros modelos.</li>
<li>Proxies, otro espacio que es necesario definir. Los proxies son subclases de nuestros modelos que el propio Doctrine crea automáticamente.</li>
</ol>
</li>
<li>Una vez que nos hemos asegurado de que todas las clases pueden cargarse automáticamente, comenzamos a crear nuestro objeto EntityManager. Para ello, <strong>lo primero es crear un objeto de tipo Configuration</strong>.</li>
<li>El primer parámetro que vamos a configurar es la caché. Podríamos haber usado <a href="http://php.net/manual/es/book.apc.php">APC</a>, el sistema de cachés de facto de PHP (aconsejable en un entorno en producción), pero para pruebas usaremos el método ArrayCache.</li>
<li>A continuación establecemos el driver con el que mapearemos nuestra base de datos. Esto es necesario para  hacer que nuestros modelos se correlacionen con nuestras bases de datos. Existen tres drivers disponibles:
<ol>
<li>XML, desde donde se puede definir como encajar el modelo con la base de datos mediante sintaxis XML.</li>
<li>YAML, al igual que con XML, también se puede definir utilizando YAML.</li>
<li>Anotaciones, que en mi opinión son una maravilla. Mediante etiquetas en comentarios PHP defines cómo se mapean los datos. Más abajo, cuando lleguemos a los modelos, veremos un ejemplo de uso.</li>
</ol>
</li>
<li>Ahora configuramos los proxies. Simplemente establecemos su directorio, y su espacio de nombres.</li>
<li>Conexión. Es aquí donde establecemos dónde se se encuentra nuestra base de datos. Si ésta no existiera, Doctrine la crearía por nosotros. En nuestro ejemplo usaremos SQLite.</li>
<li>Ya está todo listo: hemos configurado la Caché, el Driver para mapear, los proxies y la conexión. Ya podemos crear el objeto EntityManager.</li>
<li>Por último, creamos un objeto de tipo HelperSet, que es el que utilizará la utilidad de línea de comandos para saber cómo conectarse. El objeto HelperSet debe tener dos helpers: db, para identificar la conexión, y em, el EntityManager.</li>
</ol>
<p>Ya tenemos listo el fichero cli-config.php, que como dijimos, es el que se utiliza para conectar la utilidad de consola &#8216;doctrine&#8217; con nuestro proyecto.</p>
<p>Ahora vamos a ver los modelos.</p>
<pre>Entities/Adress.php</pre>
<pre class="php" name="code">&lt;?php
namespace Entities;

/** @Entity @Table(name="addresses") */
class Address
{
   /**
    * @Id @Column(type="integer")
    * @GeneratedValue(strategy="AUTO")
    */
   private $id;

   /** @Column(type="string", length=255) */
   private $street;

   /** @OneToOne(targetEntity="User", mappedBy="address") */
   private $user;

   public function getId()
   {
      return $this-&gt;id;
   }

   public function getStreet()
   {
      return $this-&gt;street;
   }

   public function setStreet($street)
   {
      $this-&gt;street = $street;
   }

   public function getUser()
   {
      return $this-&gt;user;
   }

   public function setUser(User $user)
   {
      if ($this-&gt;user !== $user) {
         $this-&gt;user = $user;
         $user-&gt;setAddress($this);
      }
   }
}</pre>
<pre>Entities/User.php</pre>
<pre class="php" name="code">&lt;?php
namespace Entities;

/** @Entity @Table(name="users") */
class User
{
   /**
    * @Id @Column(type="integer")
    * @GeneratedValue(strategy="AUTO")
    */
   private $id;

   /** @Column(type="string", length=50) */
   private $name;

   /**
    * @OneToOne(targetEntity="Address", inversedBy="user")
    * @JoinColumn(name="address_id", referencedColumnName="id")
    */
   private $address;

   public function getId()
   {
      return $this-&gt;id;
   }

   public function getName()
   {
      return $this-&gt;name;
   }

   public function setName($name)
   {
      $this-&gt;name = $name;
   }

   public function getAddress()
   {
      return $this-&gt;address;
   }

   public function setAddress(Address $address)
   {
      if ($this-&gt;address !== $address) {
         $this-&gt;address = $address;
         $address-&gt;setUser($this);
      }
   }
}</pre>
<p>No me detendré a explicar cómo se definen los modelos. En la propia documentación de Doctrine puedes ver una <a href="http://www.doctrine-project.org/docs/orm/2.0/en/reference/basic-mapping.html">introducción al mapeo</a>. Lo importante aquí es que, mediante etiquetas en los comentarios, hemos definido la relación entre la entidad User y la entidad Address, y también hemos definido cada una de sus columnas (¡hasta podemos indicar que una columna sea autoincremental!).</p>
<p>Llegados a este punto, tenemos 3 ficheros ya creados: cli-config.php, Entity/User.php y Entity/Address.php. Desde el raíz de nuestro proyecto vamos a ejecutar lo siguiente:</p>
<pre>$ doctrine orm:schema-tool:create</pre>
<p>Si todo ha ido bien, nos saldrá un mensaje indicándonos que el esquema de base de datos se ha creado correctamente. Y si comprobamos el directorio, veremos que se ha creado un nuevo fichero, database.sqlite, que contiene la definición de nuestras dos tablas. </p>
<h2>Usándolo en una aplicación web</h2>
<p>Bien, ya hemos definido las entidades, hemos creado la base de datos, y sabemos cómo funciona el código de inicialización de Doctrine 2. Ahora vamos a ver el fichero index.php:</p>
<pre class="php" name="code">
&lt;?php

// (1) Autocargamos clases
require_once 'Doctrine/Common/ClassLoader.php';
$classLoader = new \Doctrine\Common\ClassLoader('Doctrine');
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader('Entities', __DIR__);
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader('Proxies', __DIR__);
$classLoader->register();

// (2) Configuración
$config = new \Doctrine\ORM\Configuration();

// (3) Caché
$cache = new \Doctrine\Common\Cache\ArrayCache();
$config->setMetadataCacheImpl($cache);
$config->setQueryCacheImpl($cache);

// (4) Driver
$driverImpl = $config->newDefaultAnnotationDriver(array(__DIR__."/Entities"));
$config->setMetadataDriverImpl($driverImpl);

// (5) Proxies
$config->setProxyDir(__DIR__ . '/Proxies');
$config->setProxyNamespace('Proxies');

// (6) Conexión
$connectionOptions = array(
    'driver' => 'pdo_sqlite',
    'path' => 'database.sqlite'
);

// (7) EntityManager
$em = \Doctrine\ORM\EntityManager::create($connectionOptions, $config);

// (8) Código de prueba
$user = new \Entities\User();
$address = new \Entities\Address();

echo 'Hola mundo!' . PHP_EOL;

// Introduce aquí el código que maneje $user y $address
</pre>
<p>Si nos fijamos, los 7 primeros puntos son exactamente iguales que en cli-config.php. En el punto 8 creamos dos objetos de nuestro modelo, ya listos para usar. ¡Pero cuidado! Antes de poder hacer cambios en la base de datos SQLite, debes asegúrate de que el usuario de tu servidor web tiene permisos de escritura en el fichero database.sqlite. Ahora podríamos añadir el siguiente código de ejemplo:</p>
<pre class="php" name="code">
$address-&gt;setStreet("Calle Río tinto, 12");
$em-&gt;persist($address);
$em-&gt;flush();

echo "Insertamos direcci&oacute;n&lt;br /&gt;" . PHP_EOL;

$user-&gt;setName("Pedro");
$user-&gt;setAddress($address);
$em-&gt;persist($user);
$em-&gt;flush();

echo "Insertamos usuario&lt;br /&gt;" . PHP_EOL;
</pre>
<p>Simplemente tenemos que acceder desde nuestro navegador a ese fichero (o también mediante &#8220;php index.php&#8221;) para que PHP ejecute el código. Una vez hecho, podemos consultar la base de datos mediante sqlite3:</p>
<pre>
$ sqlite3 database.sqlite
SQLite version 3.6.22
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite&gt; select * from addresses;
1|Calle Río tinto, 12
sqlite&gt; select * from users;
1|1|Pedro
</pre>
<p>¡Lo ha hecho todo él sólo por nosotros! Así de sencillo resulta trabajar con bases de datos con un ORM <img src='http://chusete.es/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  A partir de aquí empieza lo bueno: ya puedes guardar tus objetos de forma persistente en base de datos, sin tener preocuparte ni por crear las tablas, ni por SQL, ni nada. Céntrate en PHP <img src='http://chusete.es/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>¡Gracias por leer!</p>
<p><a href="http://dl.dropbox.com/u/6505587/sandbox.tar.gz">Descargar el código fuente</a>
<div class="tweetmeme_button" style="float: left; margin-right: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fchusete.es%2F2011%2F02%2F19%2Fintroduccion-a-doctrine-2%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fchusete.es%2F2011%2F02%2F19%2Fintroduccion-a-doctrine-2%2F&amp;source=chuso&amp;style=normal&amp;service=bit.ly&amp;service_api=R_86054639b9f90148987197dfdc061697&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
]]></content:encoded>
			<wfw:commentRss>http://chusete.es/2011/02/19/introduccion-a-doctrine-2/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>CoRD, cliente de escritorio remoto de Mac</title>
		<link>http://chusete.es/2010/10/20/cord-cliente-de-escritorio-remoto-de-mac/</link>
		<comments>http://chusete.es/2010/10/20/cord-cliente-de-escritorio-remoto-de-mac/#comments</comments>
		<pubDate>Wed, 20 Oct 2010 00:46:45 +0000</pubDate>
		<dc:creator>chusete</dc:creator>
				<category><![CDATA[software]]></category>
		<category><![CDATA[cord]]></category>
		<category><![CDATA[escritorio remoto]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[rdp]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://chusete.es/?p=900</guid>
		<description><![CDATA[Hace unos días hablaba de mi reintroducción al mundo Windows. Para conectar desde Mac mencionaba que se podía utilizar el cliente de escritorio remoto de Microsoft. Bien, al poco de probarlo uno se da cuenta de que es un software que no está listo para producción. El teclado de un Mac es ligeramente distinto al [...]]]></description>
			<content:encoded><![CDATA[<p>Hace unos días hablaba de mi <a href="/2010/10/15/desarrollo-web-de-unix-a-windows/">reintroducción al mundo Windows</a>. Para conectar desde Mac mencionaba que se podía utilizar el cliente de escritorio remoto de Microsoft. Bien, al poco de probarlo uno se da cuenta de que es un software que no está listo para producción. El teclado de un Mac es ligeramente distinto al de un Pc convencional. Una de las diferencias es que no tiene tecla &#8220;Alt Gr&#8221;. Si utilizas un teclado inglés de EEUU, esto no te supondrá un problema, ya que no se utiliza esa tecla:</p>
<p style="text-align: center;"><a href="http://chusete.es/wp-content/uploads/2010/10/us_keyboard_layout.png"><img class="alignnone size-medium wp-image-902" title="Disposición de un teclado Inglés" src="http://chusete.es/wp-content/uploads/2010/10/us_keyboard_layout-300x100.png" alt="Disposición de un teclado Inglés" width="300" height="100" /></a></p>
<p>Pero si ése no es tu caso, el cliente de escritorio remoto de Microsoft no te servirá; no hace una conversión previa de un teclado a otro, sino que envía a Windows tal cual las teclas que has pulsado.</p>
<p>Todo esto intenté antes de dar con la solución:</p>
<ul>
<li>Utilizar otro software, como VNC.</li>
<li>Hacer uso de la combinación Alt+Ctrl, que en Windows emula la tecla AltGr. Además de ser incómodo, no muestra algunos caracteres como &#8216;{&#8216; o &#8216;\&#8217;.</li>
<li>Hacer un mapeo de teclado personalizado modificando el registro.</li>
</ul>
<p>Cuando ya creía haberlo probado todo, vi un foro en el que hablaban de <a href="http://cord.sourceforge.net/">CoRD, un cliente de escritorio remoto para Windows</a>. Lo probé, y a la primera <img src='http://chusete.es/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p style="text-align: center;"><a href="http://chusete.es/wp-content/uploads/2010/10/MediumCoRDScreenshot.jpg"><img class="alignnone size-medium wp-image-903" title="MediumCoRDScreenshot" src="http://chusete.es/wp-content/uploads/2010/10/MediumCoRDScreenshot-300x211.jpg" alt="" width="300" height="211" /></a></p>
<p>Además de contar con las mismas funcionalidades que el de Microsoft, tiene unas cuantas cosas que lo convierten en un mejor cliente RDP:</p>
<ul>
<li>Se comporta mejor en el modo pantalla completa, ajustándolo a la resolución de tu monitor. Con el de Microsoft esto no ocurría, dejando una banda negra a cada lado.</li>
<li>Interpreta y convierte de tu teclado al equivalente en Windows. Puedes escribir la arroba, llaves, almohadillas, o corchetes.</li>
<li>Convierte la tecla cmd de Mac en la tecla Win.</li>
<li>Puedes tener varias sesiones abiertas a la vez, pudiendo navegar entre ellas desde un cómodo panel.</li>
</ul>
<p>Y además, es open source!
<div class="tweetmeme_button" style="float: left; margin-right: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fchusete.es%2F2010%2F10%2F20%2Fcord-cliente-de-escritorio-remoto-de-mac%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fchusete.es%2F2010%2F10%2F20%2Fcord-cliente-de-escritorio-remoto-de-mac%2F&amp;source=chuso&amp;style=normal&amp;service=bit.ly&amp;service_api=R_86054639b9f90148987197dfdc061697&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
]]></content:encoded>
			<wfw:commentRss>http://chusete.es/2010/10/20/cord-cliente-de-escritorio-remoto-de-mac/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Probando la Beta de IE9</title>
		<link>http://chusete.es/2010/09/15/probando-la-beta-de-ie9/</link>
		<comments>http://chusete.es/2010/09/15/probando-la-beta-de-ie9/#comments</comments>
		<pubDate>Wed, 15 Sep 2010 20:01:15 +0000</pubDate>
		<dc:creator>chusete</dc:creator>
				<category><![CDATA[software]]></category>
		<category><![CDATA[beta]]></category>
		<category><![CDATA[internet explorer]]></category>

		<guid isPermaLink="false">http://chusete.es/?p=845</guid>
		<description><![CDATA[Hace meses que en todo internet venimos hablando de la inminente salida de la próxima edición de Internet Explorer. Y el momento se acerca, pues hace a penas unos minutos Microsoft ha publicado en el IEBlog la liberación de la Beta de Internet Explorer 9. Está lista para descarga en la web www.beautyoftheweb.com En 33 [...]]]></description>
			<content:encoded><![CDATA[<p>Hace meses que en todo internet venimos hablando de la inminente salida de la próxima edición de Internet Explorer. Y el momento se acerca, pues hace a penas unos minutos Microsoft ha publicado en el IEBlog la <a href="http://blogs.msdn.com/b/ie/archive/2010/09/15/ie9-beta-available-for-download.aspx">liberación de la Beta de Internet Explorer 9</a>. Está lista para descarga en la web</p>
<p><a title="Descargar IE9" href="http://www.beautyoftheweb.com/">www.beautyoftheweb.com</a></p>
<p>En 33 lenguajes. Una gran noticia tanto para usuarios como para desarrolladores. Aunque todos esperamos que finalmente Microsoft <em>recule</em> y también permita instalarlo en Windows XP -hoy por hoy sigue siendo el sistema operativo más utilizado.</p>
<p>La instalación ha sido sencillísima; Desde la web BeautyOfTheWeb descargas el instalador, y éste se encarga de todo. Tras un reinicio, nuestro Windows ya está actualizado con IE9.</p>
<p>Nada más arrancarlo, detecta que hay numerosos addons que ralentizan el inicio del programa, de modo que nos muestra una ventana desde la que desactivar aquéllos que queramos, indicándonos también el tiempo que le toma a cada addon arrancar. Un detalle que se agradece mucho, y con el que estoy seguro que usuarios no avanzados sabrán maximizar el rendimiento de su navegador.</p>
<p>Una vez arrancado y listo para funcionar, nos encontramos con un navegador limpio, muy limpio. En mi opinión, más incluso que Google Chrome, puesto que en una sola fila localizamos:</p>
<ol>
<li>botones de avanzar y retroceder</li>
<li>barra de navegación, con búsquedas, recargas, y detención.</li>
<li>pestañas</li>
<li>botones de inicio, favoritos y herramientas</li>
</ol>
<p>Esto es todo <img src='http://chusete.es/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h3>Compatibilidad con estándares</h3>
<p>Pero lo primero es lo primero. Al comprobar el rendimiento de esta nueva versión con el conocido <a href="http://acid3.acidtests.org">test Acid 3</a>, esperaríamos conseguir un buen resultado cercano al 100. Pero eso no es así, obteniendo un 70:</p>
<p><a href="http://chusete.es/wp-content/uploads/2010/09/acid-test.png"><img class="alignnone size-medium wp-image-846" title="Acid 3 test en IE9" src="http://chusete.es/wp-content/uploads/2010/09/acid-test-300x205.png" alt="" width="300" height="205" /></a></p>
<p>Enorme FAIL, pero hay que entender que aun está en fase Beta y esto puede cambiar mucho en las próximas semanas.</p>
<h3>Barra de navegación</h3>
<p>Por lo demás, podemos comprobar cómo la barra de navegación es enormemente similar a la omnibar de Google Chrome, aunando buscador y barra de direcciones en uno, si bien se echa de menos prefijos de búsqueda como los que tenemos en Konqueror o en Chrome.</p>
<p><a href="http://chusete.es/wp-content/uploads/2010/09/ie-bar.png"><img class="alignnone size-medium wp-image-847" title="ie bar" src="http://chusete.es/wp-content/uploads/2010/09/ie-bar-300x191.png" alt="" width="300" height="191" /></a></p>
<h3>Gestor de descargas</h3>
<p>Otras de las novedades que han sido desveladas ha sido el esperado gestor de descargas. Sencillo pero completo. Incluye una lista de los ficheros descargados, la localización, y las acciones posibles.</p>
<p><a href="http://chusete.es/wp-content/uploads/2010/09/ie-downloads.png"><img class="alignnone size-medium wp-image-848" title="ie downloads" src="http://chusete.es/wp-content/uploads/2010/09/ie-downloads-300x227.png" alt="" width="300" height="227" /></a></p>
<h3>Developer Tools</h3>
<p>De agradecer son estas herramientas, muy similares de nuevo a las de Google Chrome. Tenemos las siguientes secciones:</p>
<ul>
<li>HTML</li>
<li>CSS</li>
<li>Consola</li>
<li>Script</li>
<li>Profiler (¡viva!)</li>
<li>Network</li>
</ul>
<p><a href="http://chusete.es/wp-content/uploads/2010/09/ie-dev-tools.png"><img class="alignnone size-medium wp-image-849" title="ie dev tools" src="http://chusete.es/wp-content/uploads/2010/09/ie-dev-tools-300x203.png" alt="" width="300" height="203" /></a></p>
<h3>Otras consideraciones</h3>
<p>Seguimos teniendo el botón de vista de compatibilidad. Personalmente lo veo innecesario, ya que al ser esta versión compatible con las anteriores, las páginas web específicas para una edición anterior podría hacer uso de las <a href="http://msdn.microsoft.com/en-us/library/cc288325(VS.85).aspx#SetMode">etiquetas meta destinadas al efecto</a>.</p>
<p>Respecto a su limpieza, echo de más dos cosas: El botón &#8220;detener&#8221;, que bien podría ir junto al de refrescar, y el botón &#8220;página de inicio&#8221;.</p>
<p>Y en el menú de opciones podemos comprobar cómo no han innovado mucho, dando la sensación de volver al pasado al ser tan parecida a la de IE6</p>
<p><a href="http://chusete.es/wp-content/uploads/2010/09/ie-options.png"><img class="alignnone size-medium wp-image-850" title="ie options" src="http://chusete.es/wp-content/uploads/2010/09/ie-options-234x300.png" alt="" width="234" height="300" /></a></p>
<p>En resumen: Si bien se percibe en el rendimiento claramente que estamos ante una Beta, queda claro que Microsoft ha decidido no quedarse atrás. Una interfaz muy cuidada, un engine que promete, muy usable, y esperemos que ágil.
<div class="tweetmeme_button" style="float: left; margin-right: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fchusete.es%2F2010%2F09%2F15%2Fprobando-la-beta-de-ie9%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fchusete.es%2F2010%2F09%2F15%2Fprobando-la-beta-de-ie9%2F&amp;source=chuso&amp;style=normal&amp;service=bit.ly&amp;service_api=R_86054639b9f90148987197dfdc061697&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
]]></content:encoded>
			<wfw:commentRss>http://chusete.es/2010/09/15/probando-la-beta-de-ie9/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Google ya indexa SVG, mientras IE9 mejora su implementación</title>
		<link>http://chusete.es/2010/09/01/google-ya-indexa-svg-mientras-ie9-mejora-su-implementacion/</link>
		<comments>http://chusete.es/2010/09/01/google-ya-indexa-svg-mientras-ie9-mejora-su-implementacion/#comments</comments>
		<pubDate>Wed, 01 Sep 2010 17:35:57 +0000</pubDate>
		<dc:creator>chusete</dc:creator>
				<category><![CDATA[desarrollo]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[ie9]]></category>
		<category><![CDATA[svg]]></category>

		<guid isPermaLink="false">http://chusete.es/?p=832</guid>
		<description><![CDATA[SVG, el estándar del w3c para gráficos vectoriales, está dando mucho de qué hablar. Hasta ahora su uso no ha sido muy extendido, e incluso muchos diseñadores y programadores web ni siquiera lo conocen. Es posible que esto cambie poco a poco. Estos días ha habido dos importantes novedades que seguro ayudarán a impulsar esta [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://es.wikipedia.org/wiki/SVG">SVG</a>, el estándar del w3c para gráficos vectoriales, está dando mucho de qué hablar. Hasta ahora su uso no ha sido muy extendido, e incluso muchos diseñadores y programadores web ni siquiera lo conocen. Es posible que esto cambie poco a poco.</p>
<p><a href="http://www.inkscape.org/showcase/branding/index.php?lang=en"><img class="alignnone" title="Ejemplo en SVG" src="http://www.inkscape.org/showcase/branding/suse_studio_fun_inkscape.png" alt="Ejemplo en SVG" width="400" height="300" /></a></p>
<p>Estos días ha habido dos importantes novedades que seguro ayudarán a impulsar esta tecnología.</p>
<h2>Google ahora indexa SVG</h2>
<p>Por una parte, desde hoy Google <a href="http://googlewebmastercentral.blogspot.com/2010/08/google-now-indexes-svg.html">indexa los ficheros SVG</a>, tanto si está empotrado dentro de un documento HTML como si está en su propio fichero. Podemos ver ejemplos de cómo funcionan estas búsquedas: <a href="http://www.google.com/search?q=sitemap+site:fastsvg.com">Ejemplo 1</a> y <a href="http://www.google.com/search?q=HideShow+site%3Asvg-whiz.com">Ejemplo 2</a>. De modo que ya cuentan con <a href="http://www.google.com/support/webmasters/bin/answer.py?hl=en&amp;answer=35287">un tipo de fichero más</a> a sumar a su extensa lista.</p>
<p>Una de las ventajas más evidentes es que esto impulsará el uso de SVG respecto a Flash. Recordemos que una de las principales funcionalidades de Flash es poder emplear gráficos vectoriales y animaciones en la web, cosa que también se puede realizar con SVG y JavaScript. Salvo que en el caso de Flash, la indexación de contenidos siempre ha sido bastante pobre. Esto con SVG parece que no pasará <img src='http://chusete.es/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h2>IE9 se hace amigo de SVG</h2>
<p>Y la segunda noticia viene de mano de Microsoft. Precisamente ayer publicaban en el IEBlog un artículo animándonos a que nos <a href="http://blogs.msdn.com/b/ie/archive/2010/08/31/getting-ready-for-svg-open.aspx">preparemos para SVG</a>. A la vista de los resultados, han hecho una estupenda implementación de este estándar en su próximo navegador. Muestran además cómo se comporta, además de algunas pruebas en distintos navegadores.</p>
<p>Es de agradecer también que publiquen ejemplos de uso. No puedo evitar recordar mis inicios con la informática, cuando dibujaba polígonos en Basic o indagaba con la aplicación de renderizado 3d <a href="http://en.wikipedia.org/wiki/POV-Ray">POV-Ray</a>. Afortundamente, contamos con <a href="http://www.inkscape.org/">fantásticas aplicaciones</a> para dibujar nuestros gráficos en SVG.</p>
<p>Recordemos que IE9 no saldrá hasta finales de 2010, a pesar de que este mes veremos la primera beta.
<div class="tweetmeme_button" style="float: left; margin-right: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fchusete.es%2F2010%2F09%2F01%2Fgoogle-ya-indexa-svg-mientras-ie9-mejora-su-implementacion%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fchusete.es%2F2010%2F09%2F01%2Fgoogle-ya-indexa-svg-mientras-ie9-mejora-su-implementacion%2F&amp;source=chuso&amp;style=normal&amp;service=bit.ly&amp;service_api=R_86054639b9f90148987197dfdc061697&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
]]></content:encoded>
			<wfw:commentRss>http://chusete.es/2010/09/01/google-ya-indexa-svg-mientras-ie9-mejora-su-implementacion/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Internet Explorer 9 sigue imparable</title>
		<link>http://chusete.es/2010/08/05/internet-explorer-9-sigue-imparable/</link>
		<comments>http://chusete.es/2010/08/05/internet-explorer-9-sigue-imparable/#comments</comments>
		<pubDate>Thu, 05 Aug 2010 00:31:50 +0000</pubDate>
		<dc:creator>chusete</dc:creator>
				<category><![CDATA[software]]></category>
		<category><![CDATA[acid]]></category>
		<category><![CDATA[ie9]]></category>
		<category><![CDATA[internet explorer]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jscript]]></category>

		<guid isPermaLink="false">http://chusete.es/?p=805</guid>
		<description><![CDATA[Todos estamos siendo testigos del empujón que están dando desde Microsoft a la próxima versión de su navegador, Internet Explorer 9. Si bien hace poco veíamos que ya obtenía una puntuación de 83/100 en el Acid3 test, su última Plaform Preview ya logra un increíble 95/100. Y es que ya es la Fourth Platform Preview, [...]]]></description>
			<content:encoded><![CDATA[<p>Todos estamos siendo testigos del empujón que están dando desde Microsoft a la próxima versión de su navegador, Internet Explorer 9. Si bien hace poco veíamos que ya obtenía una puntuación de 83/100 en el <a href="http://en.wikipedia.org/wiki/Acid3">Acid3 test</a>, su <a href="http://blogs.msdn.com/b/ie/archive/2010/08/04/html5-modernized-fourth-ie9-platform-preview-available-for-developers.aspx">última Plaform Preview</a> ya logra un increíble <strong>95/100</strong>.</p>
<p><a href="http://chusete.es/wp-content/uploads/2010/08/Dean_PPB4_8.png"><img class="alignnone size-medium wp-image-807" title="Dean_PPB4_8" src="http://chusete.es/wp-content/uploads/2010/08/Dean_PPB4_8-300x251.png" alt="" width="300" height="251" /></a></p>
<p>Y es que ya es la Fourth Platform Preview, la versión que precede a la Beta de IE9, donde ya podremos probar de verdad cómo funciona el nuevo navegador.</p>
<p>Una de las principales novedades que trae es la aceleración hardware HTML5, esto es, aceleración completa tanto en texto, gráficos, audio y vídeo. Presentan una completa lista de ejemplos demostrando el rendimiento del navegador, comparándolo además con otros.</p>
<p>SVG, ya plenamente funciona dentro de IE9. Lo venden, no sólo como una herramienta para realizar diagramas estáticos, sino como un una excelente elección que permite crear un nuevo escenario de animaciones.</p>
<p>La integración nativa de JavaScript, hasta ahora una pieza fuera del navegador. En IE9, su nuevo motor de <a href="http://en.wikipedia.org/wiki/Chakra_(JScript_engine)">JavaScript (Chakra)</a>, mejora muy notablemente el rendimiento si lo comparamos con sus antecesores. Como nota curiosa, parece que ya oficialmente han abandonado la terminología JScript para referirse a JavaScript. Además, han <a href="http://ie.microsoft.com/TestDrive/HTML5/DOMCapabilities/">mejorado el árbol DOM</a>.</p>
<p><a href="http://chusete.es/wp-content/uploads/2010/08/Dean_PPB4_6.png"><img class="alignnone size-medium wp-image-808" title="Dean_PPB4_6" src="http://chusete.es/wp-content/uploads/2010/08/Dean_PPB4_6-300x211.png" alt="" width="300" height="211" /></a></p>
<p>Vemos también como siguen mejorando posiciones en la batalla por el mejor motor de JavaScript, superando ya las últimas versiones de Safari y de Firefox.</p>
<p>Todo parece indicar que para finales de este año, cuando salga IE9, realmente va a suponer el principio de una revolución en la web, ya que podremos por fin empezar a usar HTML5. Sólo veo una pega: No estará disponible para Windows XP, que a día de hoy, mantiene todavía una cuota de mercado de casi el 60%.</p>
<p><a href="http://">Más información, en IEBlog</a>.</p>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 818px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">http://blogs.msdn.com/b/ie/archive/2010/08/04/html5-modernized-fourth-ie9-platform-preview-available-for-developers.aspx</div>
<div class="tweetmeme_button" style="float: left; margin-right: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fchusete.es%2F2010%2F08%2F05%2Finternet-explorer-9-sigue-imparable%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fchusete.es%2F2010%2F08%2F05%2Finternet-explorer-9-sigue-imparable%2F&amp;source=chuso&amp;style=normal&amp;service=bit.ly&amp;service_api=R_86054639b9f90148987197dfdc061697&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
]]></content:encoded>
			<wfw:commentRss>http://chusete.es/2010/08/05/internet-explorer-9-sigue-imparable/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Crear un componente en Joomla! 1.5</title>
		<link>http://chusete.es/2010/08/03/crear-un-componente-en-joomla-1-5/</link>
		<comments>http://chusete.es/2010/08/03/crear-un-componente-en-joomla-1-5/#comments</comments>
		<pubDate>Tue, 03 Aug 2010 19:00:02 +0000</pubDate>
		<dc:creator>chusete</dc:creator>
				<category><![CDATA[php]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[componentes]]></category>
		<category><![CDATA[extensiones]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[joomla]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://chusete.es/?p=793</guid>
		<description><![CDATA[Joomla! es, junto con WordPress, quizás el CMS más popular que existe. Lo que no mucha gente sabe, o tiene en cuenta, es que es además un completo Framework de desarrollo web. No en vano, nos proporciona muchas de las funcionalidades que esperamos de un Framework: Arquitectura basada en Modelo-Vista-Controlador. Seguridad, con un completo sistema [...]]]></description>
			<content:encoded><![CDATA[<p>Joomla! es, junto con WordPress, quizás el CMS más popular que existe. Lo que no mucha gente sabe, o tiene en cuenta, es que es además un completo <a href="http://docs.joomla.org/Framework">Framework de desarrollo web</a>. No en vano, nos proporciona muchas de las funcionalidades que esperamos de un Framework:</p>
<ul>
<li>Arquitectura basada en Modelo-Vista-Controlador.</li>
<li>Seguridad, con un completo sistema de perfiles de acceso.</li>
<li>Acceso a base de datos.</li>
<li>Sistema de cachés.</li>
<li>Gestión de errores.</li>
<li>Administración de formularios.</li>
<li>Sesiones.</li>
<li>Plantillas.</li>
<li>Utilidades para fechas, criptografía, XML, ficheros&#8230;</li>
</ul>
<p>Con todo esto, podemos crear diferentes <a href="http://docs.joomla.org/Extension">extensiones de Joomla</a>!:</p>
<ul>
<li><strong>Component.</strong> Son las extensiones más complejas. Se trata de aplicaciones completas que se ejecutan dentro del espacio de Joomla!. Tenemos muchas de serie, como por ejemplo el componente Content (/components/com_content/), que es el encargado de manejar los artículos, categorías y secciones.</li>
<li><strong>Module.</strong> Se trata de pequeñas piezas de contenido que se muestran en la página. A menudo, dependen de un componente, como es el caso del módulo &#8220;latest news&#8221; (/modules/mod_latestnews/). Otro ejemplo de módulos, son los menús. En los módulos, además, se debe especificar su posición dentro de la página.</li>
<li><strong>Plugins.</strong> Son bloques de código que se disparan ante determinados eventos. Antes de Joomla! 1.5 se los llamaba Mambots.</li>
<li><strong>Templates.</strong> Plantillas que modifican el aspecto visual de la aplicación web.</li>
<li><strong>Languages.</strong> Las extensiones de este tipo contienen ficheros que definen cadenas de texto traducidas para distintas partes de Joomla!.</li>
</ul>
<p>A partir de Joomla 1.6, además, tendremos dos nuevos tipos de extensiones. <strong>Library</strong>, que se tratará de un bloque de código que contenta un conjunto de funciones relacionadas entre sí. Por ejemplo, para acceder a la API de Twitter. Y también se incluirá la extensión <strong>Packages</strong>.</p>
<p>Como vemos, la extensión más compleja y flexible son los components. Con ellos podremos crear, por ejemplo, una completa agenda de eventos o un sistema de ecommerce. Veamos cómo podemos crear un componente básico &#8220;Hola Mundo&#8221;. Vamos a utilizar la primera parte del <a href="http://docs.joomla.org/Developing_a_Model-View-Controller_Component_-_Part_1">ejemplo</a> que viene en la documentación de Joomla!.</p>
<h2>Modelo Vista Controlador</h2>
<p>Lo primero es conocer el patrón <a href="http://es.wikipedia.org/wiki/Modelo_Vista_Controlador">Modelo-Vista-Controlador</a>. Queda fuera del alcance de este artículo explicar en qué consiste, de modo que en resumen diremos que se trata de una arquitectura que permite dividir una aplicaciones en tres apartados:</p>
<ol>
<li><strong>Controlador</strong>, que es el que gobierna el comportamiento principal, y el que responde las peticiones del usuario. En Joomla: JController.</li>
<li><strong>Vista</strong>. Se trata del código que se encarga de generar el contenido que se le devolverá al usuario. Generalmente en HTML. En Joomla: JView.</li>
<li><strong>Modelo</strong>. Es una abstracción de los datos que usa la aplicación. Si bien normalmente encapsulan bases de datos, también pueden utilizar otros origines de datos como un feed RSS. En Joomla: JModel.</li>
</ol>
<h2>Crear árbol de directorios</h2>
<p>El primer paso consiste en crear el siguiente árbol de directorio y ficheros:</p>
<p><a href="http://chusete.es/wp-content/uploads/2010/08/Captura-de-pantalla-2010-08-03-a-las-20.09.47.png"><img class="alignnone size-full wp-image-794" title="Captura de pantalla 2010-08-03 a las 20.09.47" src="http://chusete.es/wp-content/uploads/2010/08/Captura-de-pantalla-2010-08-03-a-las-20.09.47.png" alt="" width="433" height="322" /></a></p>
<p>Además de los ficheros en blanco index.html (Para prevenir accesos a los directorios), vemos que tenemos 5 ficheros:</p>
<ol>
<li>/site/hello.php &#8211; Punto de entrara a nuestro componente</li>
<li>/site/controller.php &#8211; Fichero que contiene nuestro controlador.</li>
<li>/site/views/hello/view.html.php &#8211; Clase que extiende JView que se encarga de construir la vista</li>
<li>/site/views/hello/tmpl/default.php &#8211; Plantilla</li>
<li>/hello.xml &#8211; Fichero XML que indica a Joomla! cómo instalar el componente.</li>
</ol>
<h2>Crear el punto de entrada</h2>
<p>Vamos a editar el fichero /site/hello.php y vamos a guardar en el lo siguiente:</p>
<pre name="code" class="php">/**
 * @package    Joomla.Tutorials
 * @subpackage Components
 * components/com_hello/hello.php
 * @link http://docs.joomla.org/Developing_a_Model-View-Controller_Component_-_Part_2
 * @license    GNU/GPL
 */

// No direct access
defined( '_JEXEC' ) or die( 'Restricted access' );

// Require the base controller

require_once( JPATH_COMPONENT.DS.'controller.php' );

// Require specific controller if requested
if ($controller = JRequest::getWord('controller')) {
	$path = JPATH_COMPONENT.DS.'controllers'.DS.$controller.'.php';
	if (file_exists($path)) {
		require_once $path;
	} else {
		$controller = '';
	}
}

// Create the controller
$classname	= 'HelloController'.$controller;
$controller	= new $classname();

// Perform the Request task
$controller-&gt;execute( JRequest::getVar( 'task' ) );

// Redirect if set by the controller
$controller-&gt;redirect();</pre>
<p>¿Qué es lo que hemos hecho? Veámoslo paso a paso:</p>
<ol>
<li>En primer lugar comprobamos que estamos ejecutando éste código dentro de Joomla mirando si está definido _JEXEC. En caso contrario, finalizamos la aplicación.</li>
<li>Cargamos con require_once nuestro controlador.</li>
<li>El siguiente bloque de código comprueba si se necesitan más controladores. Por ahora no es necesario, pero lo mantenemos ahí para un futuro.</li>
<li>Después, creamos el controlador. En este caso, siempre se creará un controlador de la clase HelloController(), dado que en este ejemplo, como vimos en el paso anterior, no hay más.</li>
<li>Posteriormente indicamos al controlador que lleve a cabo la tarea solicitada. Por defecto, si no hay ninguna, la tarea es &#8216;display&#8217;.</li>
<li>Finalmente, pasamos el control al controlador, para que, si fuera necesario, lleve a cabo una redirección.</li>
</ol>
<h2>Creamos el controlador</h2>
<p>Nuestro controlador sólo hace una cosa: Mostrar el mensaje Hello World, de modo que no se hace necesaria ninguna manipulación de datos. Guardamos el siguiente código en /site/controller.php</p>
<pre name="code" class="php"> /**
 * @package    Joomla.Tutorials
 * @subpackage Components
 * @link http://docs.joomla.org/Developing_a_Model-View-Controller_Component_-_Part_1
 * @license    GNU/GPL
 */

// No direct access

defined( '_JEXEC' ) or die( 'Restricted access' );

jimport('joomla.application.component.controller');

/**
 * Hello World Component Controller
 *
 * @package    Joomla.Tutorials
 * @subpackage Components
 */
class HelloController extends JController
{
    /**
     * Method to display the view
     *
     * @access    public
     */
    function display()
    {
        parent::display();
    }

}</pre>
<p>Como vemos, creamos una clase llamada HelloController que hereda a JController. Tan sólo define el método display(), pues es la tarea por defecto (Salvo que no se especifique otra). Este método tan sólo invoca al método JController::display(), que determina y carga la vista y plantilla a utilizar. En nuestro ejemplo, sólo tenemos una vista y una plantilla.</p>
<h2>Crear la vista</h2>
<p>La vista tan sólo carga datos y los guarda para usar en la plantilla. Para ello se usa el método assignRef(), donde el primer parámetro es el nombre de la variable en la plantilla, y el segundo la variable que se comparte.</p>
<p>Código de /site/views/hello/view.html.php:</p>
<pre name="code" class="php">/**
 * @package    Joomla.Tutorials
 * @subpackage Components
 * @link http://docs.joomla.org/Developing_a_Model-View-Controller_Component_-_Part_1
 * @license    GNU/GPL
*/

// no direct access

defined( '_JEXEC' ) or die( 'Restricted access' );

jimport( 'joomla.application.component.view');

/**
 * HTML View class for the HelloWorld Component
 *
 * @package    HelloWorld
 */

class HelloViewHello extends JView
{
    function display($tpl = null)
    {
        $greeting = "Hello World!";
        $this-&gt;assignRef( 'greeting', $greeting );

        parent::display($tpl);
    }
}</pre>
<p>Y ahora definimos el código de la plantilla en /site/views/hello/tmpl/default.php:</p>
<pre name="code" class="php">&lt;?php

// No direct access

defined('_JEXEC') or die('Restricted access'); ?&gt;
<h1>&lt;?php echo $this->greeting; ?&gt;</h1>
</pre>
<p>Se trata de un fichero PHP convencional en el que tenemos accesibles todas las variables que hemos compartido desde la vista.</p>
<h2>Juntándolo todo</h2>
<p>Nos queda definir el fichero Manifiest que define el componente para poder instalarlo fácilmente (Sin tener que copiar los ficheros a mano y actualizar la base de datos nosotros). Contiene distinta información, como por ejemplo:</p>
<ul>
<li>Descripción del componente.</li>
<li>Lista de ficheros que incluye.</li>
<li>Un fichero opcional PHP que realizar tareas de instalación.</li>
<li>Un fichero opcional SQL que se ejecuta al instalar o desinstalar</li>
</ul>
<pre name="code" class="xml"><?xml version="1.0" encoding="utf-8"?>
<install type="component" version="1.5.0">
 <name>Hello</name>
 <!-- The following elements are optional and free of formatting constraints -->
 <creationDate>2007-02-22</creationDate>
 <author>John Doe</author>
 <authorEmail>john.doe@example.org</authorEmail>
 <authorUrl>http://www.example.org</authorUrl>
 <copyright>Copyright Info</copyright>
<license>License Info</license>
 <!--  The version string is recorded in the components table -->
 <version>1.01</version>
 <!-- The description is optional and defaults to the name -->
 <description>Description of the component ...</description>

 <!-- Site Main File Copy Section -->
 <!-- Note the folder attribute: This attribute describes the folder
      to copy FROM in the package to install therefore files copied
      in this section are copied from /site/ in the package -->
 <files folder="site">
  <filename>controller.php</filename>
  <filename>hello.php</filename>
  <filename>index.html</filename>
  <filename>views/index.html</filename>
  <filename>views/hello/index.html</filename>
  <filename>views/hello/view.html.php</filename>
  <filename>views/hello/tmpl/default.php</filename>
  <filename>views/hello/tmpl/index.html</filename>
 </files>

 <administration>
  <!-- Administration Menu Section -->
<menu>Hello World!</menu>

  <!-- Administration Main File Copy Section -->
  <files folder="admin">
   <filename>hello.php</filename>
   <filename>index.html</filename>
  </files>

 </administration>
</install>
</pre>
<p>Finalmente, guardamos en los ficheros index.html un contenido trivial, como por ejemplo:</p>
<pre name="code" class="html">
&lt;html&gt;&lt;body bgcolor="#FFFFFF"&gt;&lt;/body&gt;&lt;/html&gt;
</pre>
<p>Por último, comprimimos en un fichero ZIP el contenido de la carpeta com_hello, y ya podemos instalar nuestro componente desde el instalador de extensiones de Joomla.</p>
<h2>Mostrando el componente</h2>
<p>Ahora, para poder ver el resultado, debemos consultar el componente. Para ello, debemos acceder a la siguiente URL:</p>
<p>/index.php?option=com_hello&amp;view=hello</p>
<p>Vemos que no se define ninguna tarea (Recordemos que por defecto se usa Display). En caso de querer ejecutar otra tarea, tendríamos que definir el parámetro GET task, por ejemplo para la tarea &#8216;save&#8217;:</p>
<p>/index.php?option=com_hello&amp;view=hello&amp;task=save
<div class="tweetmeme_button" style="float: left; margin-right: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fchusete.es%2F2010%2F08%2F03%2Fcrear-un-componente-en-joomla-1-5%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fchusete.es%2F2010%2F08%2F03%2Fcrear-un-componente-en-joomla-1-5%2F&amp;source=chuso&amp;style=normal&amp;service=bit.ly&amp;service_api=R_86054639b9f90148987197dfdc061697&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
]]></content:encoded>
			<wfw:commentRss>http://chusete.es/2010/08/03/crear-un-componente-en-joomla-1-5/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Quitar iconos de PDF, Mail e Imprimir en Joomla</title>
		<link>http://chusete.es/2010/08/03/quitar-iconos-de-pdf-mail-e-imprimir-en-joomla/</link>
		<comments>http://chusete.es/2010/08/03/quitar-iconos-de-pdf-mail-e-imprimir-en-joomla/#comments</comments>
		<pubDate>Tue, 03 Aug 2010 14:47:59 +0000</pubDate>
		<dc:creator>chusete</dc:creator>
				<category><![CDATA[software]]></category>
		<category><![CDATA[configuracion]]></category>
		<category><![CDATA[iconos]]></category>
		<category><![CDATA[joomla]]></category>

		<guid isPermaLink="false">http://chusete.es/?p=789</guid>
		<description><![CDATA[A veces las tareas más sencillas son las que más se me complican. Un ejemplo es la gestión de Joomla!, conocido CMS por su sencillez y comunidad, pero que al menos a mí a veces me resulta bastante complicado. Supongo que debe ser porque mi enfoque es el de un programador, y me cuesta resolver [...]]]></description>
			<content:encoded><![CDATA[<p>A veces las tareas más sencillas son las que más se me complican. Un ejemplo es la gestión de Joomla!, conocido CMS por su sencillez y comunidad, pero que al menos a mí a veces me resulta bastante complicado. Supongo que debe ser porque mi enfoque es el de un programador, y me cuesta resolver problemas típicamente de programación a golpe de ratón.</p>
<p>En este caso en concreto, se trata de establecer las configuraciones por defecto de los artículos en Joomla!, esto es, los parámetros avanzados que se pueden configurar para cada artículo en el menú de la derecha. El método de fuerza bruta es ir artículo por artículo quitándolo. Pero esto no escala <img src='http://chusete.es/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Pues bien, si queremos desactivar de una vez por todas los iconos de exportar a PDF, enviar por email e imprimir, simplemente debemos ir al menú Contenidos, apartado Gestor de artículos. Una vez ahí, pulsamos el botón Preferencias, y ya podremos activar los valores por defecto.</p>
<p><a href="http://chusete.es/wp-content/uploads/2010/08/Captura-de-pantalla-2010-08-03-a-las-16.39.54.png"><img class="alignnone size-thumbnail wp-image-790" title="Preferencias globales de artículos" src="http://chusete.es/wp-content/uploads/2010/08/Captura-de-pantalla-2010-08-03-a-las-16.39.54-150x150.png" alt="" width="150" height="150" /></a></p>
<p>Simplemente marcamos la opción &#8220;ocultar&#8221; de los campos:</p>
<ul>
<li>Iconos</li>
<li>Icono PDF</li>
<li>Icono Imprimir</li>
<li>Icono e-mail</li>
</ul>
<p>Y de paso, para quitar más <em>basura</em>, oculto también:</p>
<ul>
<li>Nombre del autor</li>
<li>Creado en fecha y hora</li>
<li>Modificado en fecha y hora</li>
<li>Muestra navegación</li>
<li>Enlace leer más&#8230;</li>
<li>Valoración/Votación de artículos</li>
<li>Impresiones</li>
<li>Nombre de la sección</li>
<li>Título de la categoría</li>
</ul>
<p>De esta forma, Joomla! parecerá un poquito menos Joomla!, algo que siempre procuro hacer con todo CMS: Que no se aprecie el software que hay por debajo.
<div class="tweetmeme_button" style="float: left; margin-right: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fchusete.es%2F2010%2F08%2F03%2Fquitar-iconos-de-pdf-mail-e-imprimir-en-joomla%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fchusete.es%2F2010%2F08%2F03%2Fquitar-iconos-de-pdf-mail-e-imprimir-en-joomla%2F&amp;source=chuso&amp;style=normal&amp;service=bit.ly&amp;service_api=R_86054639b9f90148987197dfdc061697&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
]]></content:encoded>
			<wfw:commentRss>http://chusete.es/2010/08/03/quitar-iconos-de-pdf-mail-e-imprimir-en-joomla/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>¿Qué diferencias hay entre Google Chrome y Chromium?</title>
		<link>http://chusete.es/2009/12/09/%c2%bfque-diferencias-hay-entre-google-chrome-y-chromium/</link>
		<comments>http://chusete.es/2009/12/09/%c2%bfque-diferencias-hay-entre-google-chrome-y-chromium/#comments</comments>
		<pubDate>Wed, 09 Dec 2009 03:20:03 +0000</pubDate>
		<dc:creator>chusete</dc:creator>
				<category><![CDATA[software]]></category>
		<category><![CDATA[Chromium]]></category>
		<category><![CDATA[Google Chrome]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[Theora]]></category>
		<category><![CDATA[Vorbis]]></category>

		<guid isPermaLink="false">http://chusete.es/?p=654</guid>
		<description><![CDATA[Es posible que, al igual que a mí, os haya surgido esa duda. Si bien desde hoy tenemos a nuestra disposición Google Chrome para Linux y de Mac, hace tiempo que podíamos disfrutar de Chromium. ¿No habíamos quedado en que era lo mismo? ¿Qué diferencias hay? Voy a tratar de dar respuesta a estas dudas. [...]]]></description>
			<content:encoded><![CDATA[<p>Es posible que, al igual que a mí, os haya surgido esa duda. Si bien desde hoy tenemos a nuestra disposición <a href="http://chrome.blogspot.com/2009/12/google-chrome-for-holidays-mac-linux.html">Google Chrome para Linux y de Mac</a>, hace tiempo que podíamos disfrutar de Chromium. ¿No habíamos quedado en que era lo mismo? ¿Qué diferencias hay? Voy a tratar de dar respuesta a estas dudas.</p>
<p><a href="http://chusete.es/wp-content/uploads/2009/12/chrome_vs_chromium.jpg"><img class="aligncenter size-medium wp-image-655" title="chrome_vs_chromium" src="http://chusete.es/wp-content/uploads/2009/12/chrome_vs_chromium-300x128.jpg" alt="chrome_vs_chromium" width="300" height="128" /></a></p>
<p>Si consultamos la Wikipedia en castellano veremos que:</p>
<ul>
<li><em><strong>Google Chrome</strong> es un navegador web desarrollado por Google y compilado con base en componentes de código abierto [...]</em></li>
<li><em><strong>Chromium</strong> es el proyecto de software libre detrás de Google Chrome[...]</em></li>
</ul>
<p>O dicho de otra forma, Google Chrome es la compilación y el paquete que Google hace del software Chromium. Algo así como los distints paquetes que las distribuciones de GNU/Linux hacen del kernel.</p>
<p>Si eso es todo&#8230; ¿Qué más me da usar uno u otro? ¿No son lo mismo pero empaquetado por entidades diferentes? Bien, Google tiene una <a href="http://code.google.com/p/chromium/wiki/ChromiumBrowserVsGoogleChrome">página explicativa</a> al respecto que con vuestro permiso voy a traducir:</p>
<div style="background-color:#e0ecf1;padding:20px;">Chromium en Linux tiene en general dos sabores: Puedes instalar o bien Google Chrome o bien un navegador Chromium. Esta página trata de explicar la diferencia entre ambos:</p>
<p><strong>Google Chrome</strong></p>
<p>Google Chrome es el proyecto de software libre Chromium construído, empaquetado y distribuído por Google. Tiene las siguientes diferencias respecto a Chromium:</p>
<ul style="max-width: 65em; padding-left: 40px;">
<li>Logo coloreado</li>
<li>Opción de informe de errores</li>
<li>Opción de métrias de usuarios</li>
<li>Soporte para H.264, AAC, MP3, Vorbis y Theora con las etiquetas audio y video.</li>
<li>Aislamiento de procesos</li>
<li>Un sólo paquete deb/rpm</li>
<li>Los ficheros de los perfiles se almacenan en  <tt>~/.config/google-chrome</tt></li>
</ul>
<p>La compilación del canal de desarrollo se actualiza alrededor de una vez por semana, tras pasar los test automáticos y unos pocos test manuales de garantía de calidad.</p>
<p><strong>Chromium</strong></p>
<ul style="max-width: 65em; padding-left: 40px;">
<li>Logo azul</li>
<li>Soporte para Vorbis y Theora con las etiquetas video y audio</li>
<li>El aislamiento de procesos es opcional, depende del mantenedor del paquete</li>
<li>Los paquetes dependen de la distribución, a veces se dividen en múltiples partes.</li>
<li>Los ficheros de perfiles se almacenan en <tt>~/.config/chromium</tt></li>
</ul>
<p><span style="font-family: arial,sans-serif; font-size: 13px;"><a name="Chromium"></a></span></p>
<p><span style="font-family: arial,sans-serif; font-size: 13px;"><a name="Google_Chrome"></a></span></div>
<p>Bien, ahora queda un poco más claro. La principal diferencia que veo yo es el soporte para los codecs de compresión de audio y vídeo. Google, como compañía, está dispuesta a pagar royalties por la licencia de la patente de dichos codecs, no así las ediciones libres.</p>
<p>Por otra parte, mientras nada me haga pensar lo contrario, creo que el nivel de calidad que ofrecen las distribuciones Linux en general es bastante elevado, por lo que no considero que ese hecho otorgue ventaja a Google Chrome.</p>
<p>¿Cuál elegir? Yo personalmente seguiré usando Chromium como navegador secundario y Firefox como primario. Principalmente para promover el uso de tecnologías libres y estándar, como son <a href="http://en.wikipedia.org/wiki/Vorbis">Vorbis</a> para el audio y <a href="http://en.wikipedia.org/wiki/Theora">Theora</a> para el vídeo.
<div class="tweetmeme_button" style="float: left; margin-right: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fchusete.es%2F2009%2F12%2F09%2F%25c2%25bfque-diferencias-hay-entre-google-chrome-y-chromium%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fchusete.es%2F2009%2F12%2F09%2F%25c2%25bfque-diferencias-hay-entre-google-chrome-y-chromium%2F&amp;source=chuso&amp;style=normal&amp;service=bit.ly&amp;service_api=R_86054639b9f90148987197dfdc061697&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
]]></content:encoded>
			<wfw:commentRss>http://chusete.es/2009/12/09/%c2%bfque-diferencias-hay-entre-google-chrome-y-chromium/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>

