<?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; php</title>
	<atom:link href="http://chusete.es/category/desarrollo/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://chusete.es</link>
	<description>A la tercera va la vencida</description>
	<lastBuildDate>Tue, 13 Mar 2012 16:06:18 +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>Introducción a la programación en Facebook V</title>
		<link>http://chusete.es/2011/09/23/introduccion-a-la-programacion-en-facebook-v/</link>
		<comments>http://chusete.es/2011/09/23/introduccion-a-la-programacion-en-facebook-v/#comments</comments>
		<pubDate>Fri, 23 Sep 2011 16:27:12 +0000</pubDate>
		<dc:creator>chusete</dc:creator>
				<category><![CDATA[desarrollo]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[php sdk]]></category>
		<category><![CDATA[sdk]]></category>

		<guid isPermaLink="false">http://chusete.es/?p=1221</guid>
		<description><![CDATA[Quinta y última parte de esta guía introductoria al desarrollo de aplicaciones web sobre la Facebook Platform. Ya conoces el ecosistema de tecnologías de Facebook, sabes cómo crear distintos tipos de aplicaciones, y conoces el SDK JavaScript por completo. Hoy vamos a ver el PHP SDK. Antes de seguir leyendo, puedes echar un vistazo a [...]]]></description>
			<content:encoded><![CDATA[<p><img class="aligncenter size-full wp-image-1233" title="head_fb5" src="http://chusete.es/wp-content/uploads/2011/09/head_fb5.png" alt="" width="100%" /></p>
<p>Quinta y última parte de esta guía introductoria al desarrollo de aplicaciones web sobre la Facebook Platform. Ya conoces el ecosistema de tecnologías de Facebook, sabes cómo crear distintos tipos de aplicaciones, y conoces el SDK JavaScript por completo. Hoy vamos a ver el <a href="http://developers.facebook.com/docs/reference/php/">PHP SDK</a>.</p>
<p>Antes de seguir leyendo, puedes echar un vistazo a la página GitHub donde está alojado el <a href="https://github.com/facebook/php-sdk">proyecto PHP SDK</a>, y desde donde te lo podrás <a href="https://github.com/facebook/php-sdk/archives/master">descargar</a>. Nosotros vamos a hablar sobre la última versión estable, la 3.1.0.</p>
<h2><span id="more-1221"></span>1 Instalación</h2>
<p>Ya has dado de alta tus aplicaciones, y ahora quieres saber cómo incorporar el PHP SDK a alguna de ellas. Lo primero, deberás descargarte el SDK de su página en GitHub y descomprimirlo. Verás tres carpetas:</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-22-a-las-21.22.15.png"><img class="aligncenter size-medium wp-image-1222" title="Captura de pantalla 2011-09-22 a la(s) 21.22.15" src="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-22-a-las-21.22.15-300x152.png" alt="" width="300" height="152" /></a></p>
<p>Se incluye:</p>
<ul>
<li><strong>changelog.md</strong> &#8211; Fichero que registra todos los cambios entre las distintas versiones del SDK.</li>
<li><strong>examples</strong> &#8211; Un ejemplo de uso.</li>
<li><strong>readme.md</strong> &#8211; Fichero &#8216;léame&#8217; con documentación básica.</li>
<li><strong>src</strong> &#8211; Bibliotecas del SDK. Esta carpeta es la que usaremos en nuestro proyecto.</li>
<li><strong>tests</strong> -Batería de tests unitarios para comprobar el correcto funcionamiento del SDK.</li>
</ul>
<div>Vamos a crear una nueva carpeta, donde crearemos un fichero index.php y donde copiaremos la carpeta &#8216;src&#8217;:</div>
<div><a href="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-22-a-las-21.28.59.png"><img class="aligncenter size-full wp-image-1223" title="Captura de pantalla 2011-09-22 a la(s) 21.28.59" src="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-22-a-las-21.28.59.png" alt="" width="334" height="122" /></a></div>
<div>Ahora, editaremos el fichero index.php y añadiremos el código de inicialización del PHP SDK:</div>
<div>
<pre class="php" name="code">&lt;?php
    require_once("src/facebook.php");

    $config = array(
        'appId' =&gt; 'TU_APP_ID',
        'secret' =&gt; 'TU_APP_SECRET',
        'fileUpload' =&gt; false, // opcional
    );

    $facebook = new Facebook($config);</pre>
</div>
<p>Es decir, cargamos el SDK, creamos un nuevo array con la configuración del objeto Facebook, y finalmente lo creamos. ¡Ya está! <img src='http://chusete.es/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Ya puedes usar el PHP SDK.</p>
<h2>2 Métodos básicos</h2>
<p>Vamos a ver 6 métodos getter y setter básicos:</p>
<h3><a href="http://developers.facebook.com/docs/reference/php/facebook-getAccessToken/">Facebook::getAccessToken</a></h3>
<p>Mediante este método podremos obtener el accessToken en uso. Los access token son objetos que definen los permisos que tenemos para interactuar con un determinado usuario. Puedes ver más sobre el objeto access_token en la <a href="http://developers.facebook.com/docs/reference/api/permissions/">documentación de los permisos</a>.</p>
<h3><a href="http://developers.facebook.com/docs/reference/php/facebook-setAccessToken/">Facebook::setAccessToken</a></h3>
<p>Del mismo modo, podremos establecer el accessToken con el que funcionará nuestra aplicación. Se sobreentiende que este AccessToken ha sido obtenido por algún medio ajeno al SDK de PHP (por ejemplo, mediante cURL).</p>
<h3><a href="http://developers.facebook.com/docs/reference/php/facebook-getAppSecret/">Facebook::getApiSecret</a></h3>
<p>Nos devuelve el APP_SECRET de la aplicación.</p>
<h3><a href="http://developers.facebook.com/docs/reference/php/facebook-setAppSecret/">Facebook::setApiSecret</a></h3>
<p>Permite establecer a mano el APP_SECRET para nuestra aplicación</p>
<h3><a href="http://developers.facebook.com/docs/reference/php/facebook-getAppId/">Facebook::getAppId</a></h3>
<p>Devuelve el APP_ID de nuestra aplicación</p>
<h3><a href="http://developers.facebook.com/docs/reference/php/facebook-setAppId/">Facebook::setAppId</a></h3>
<p>Nos permite establecer a mano el APP_ID de la aplicación</p>
<h2>3 Métodos de autenticación</h2>
<p>Lo primero es lo primero. Vamos a ver cómo podremos autenticar a un usuario, y cómo solicitarle permisos. Para ello, vamos a revisar antes cuatro métodos más:</p>
<h3><a href="http://developers.facebook.com/docs/reference/php/facebook-getLoginStatusUrl/">Facebook::getLoginStatusUrl</a></h3>
<p>Este método nos permite especificar URLs según el estado de login del usuario, de manera que en función de este estado, nos redirigirá a un URL u otra. Hay tres estados posibles:</p>
<ol>
<li><strong>ok_session</strong> &#8211; El usuario ha iniciado sesión en Facebook.</li>
<li><strong>no_user</strong> &#8211; El usuario no ha iniciado sesión en Facebook.</li>
<li><strong>no_session</strong> &#8211; El usuario no está conectado a nuestra aplicación.</li>
</ol>
<p>El valor devuelto por esta URL es una dirección de Facebook que se encarga de llevar a cabo por nosotros la redirección. Puedes <a href="http://www.chusete.es/facebook/phpdemo/getLoginStatusUrl.php">probar aquí</a> para ver en funcionamiento este ejemplo:</p>
<pre name="code" class="php">    if (isset($_GET['status']) &amp;&amp; !empty($_GET['status'])) {
        switch($_GET['status']) {
            case 1: echo 'Te conozco <img src='http://chusete.es/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> '; break;
            case 2: echo 'No est&amp;aacute;s conectado a Facebook.'; break;
            case 3: echo 'Est&amp;aacute;s conectado, pero no te conozco.'; break;
        }
        echo "&lt;br /&gt;&lt;a href='http://www.chusete.es/facebook/phpdemo/getLoginStatusUrl.php'&gt;Volver a intentar&lt;/a&gt;";
    } else {
        $params = array(
            'ok_session' =&gt; 'http://www.chusete.es/facebook/phpdemo/getLoginStatusUrl.php?status=1',
            'no_user' =&gt; 'http://www.chusete.es/facebook/phpdemo/getLoginStatusUrl.php?status=2',
            'no_session' =&gt; 'http://www.chusete.es/facebook/phpdemo/getLoginStatusUrl.php?status=3',
        );

        header("Location: ".$facebook-&gt;getLoginStatusUrl($params));
    }</pre>
<h3><a href="http://developers.facebook.com/docs/reference/php/facebook-getLoginUrl/">Facebook::getLoginUrl</a></h3>
<p>Construye por nosotros la URL desde la que accedemos a la página que nos muestra el diálogo OAuth. Acepta dos parámetros:</p>
<ol>
<li><strong>scope</strong> &#8211; Como ya sabes, la lista de permisos que queremos solicitar al usuario.</li>
<li><strong>redirect_uri</strong> &#8211; Dirección a la que se redirigirá tras el diálogo OAuth.</li>
</ol>
<div>Por ejemplo:</div>
<div>
<pre name="code" class="php">    $params = array(
        'scope' =&gt; 'read_stream, friends_interests',
        'redirect_uri' =&gt; 'http://chusete.es/post_login_page',
    );

    $loginUrl = $facebook-&gt;getLoginUrl($params);</pre>
<p>De este modo, en <em>$loginUrl</em> tendremos una URL que nos mostrará el diálogo OAuth que solicita al usuario permisos para consultar su muro y para conocer los intereses de sus amigos. Tras aceptarlo, se le redirigirá a la dirección de <em>redirect_url</em>.</p>
</div>
<h3><a href="http://developers.facebook.com/docs/reference/php/facebook-getLogoutUrl/">Facebook::getLogoutUrl</a></h3>
<p>Del mismo modo que podemos generar la URL de inicio de sesión en nuestra aplicación, podemos crear otra para salir. Sólo debemos indicar un parámetro (opcional):</p>
<ul>
<li><strong>next</strong> &#8211; URL a la que se le redirigirá al usuario tras hacer logout.</li>
</ul>
<h3><a href="http://developers.facebook.com/docs/reference/php/facebook-getUser/">Facebook::getUser</a></h3>
<p>Este método tan sólo nos devuelve el ID del usuario activo en nuestra aplicación.</p>
<h2>4 Autenticación</h2>
<p>Ya tienes la aplicación creada, ya has descargado el SDK, ya has instanciado un objeto de la clase Facebook, y ya conoces los métodos necesarios. Es el momento de ver cómo hacer un inicio de sesión en nuestra aplicación <img src='http://chusete.es/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Esto es lo que va a realizar nuestro ejemplo: Cuando el usuario acceda a la aplicación, si ha conectado con ella previamente, se le mostrará un mensaje de bienvenida. En caso contrario, le reenviaremos al diálogo OAuth para solicitarle permisos. Si los acepta, volverá a la aplicación, donde le daremos la bienvenida y le daremos la opción de cerrar sesión. En caso contrario, le mostraremos un mensaje lamentando que no haya conectado con nuestra súper app. Puedes ver <a href="http://chusete.es/facebook/phpdemo/">aquí la demo</a>.</p>
<p>Éste es el código:</p>
<pre name="code" class="php">    $params = array(
        'scope' =&gt; 'read_stream, friends_interests',
        'redirect_uri' =&gt; 'http://chusete.es/facebook/phpdemo/',
    );
    $loginUrl = $facebook-&gt;getLoginUrl( $params );

    if ( $_GET['error'] ) {
        echo "Parece que no quieres usar la aplicaci&amp;oacute;n <img src='http://chusete.es/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> &lt;br /&gt;";
        echo "Si cambias de opini&amp;oacute;n, haz clic &lt;a href='".$loginUrl."'&gt;aqu&amp;iacute;&lt;/a&gt;";
    } elseif( $facebook-&gt;getUser() ) {
        $logoutUrl = $facebook-&gt;getLogoutUrl(array('next' =&gt; 'http://www.facebook.com/'));
        echo "Bienvenido! <img src='http://chusete.es/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> &lt;br /&gt;";
        echo "Puedes &lt;a href='".$logoutUrl."'&gt;cerrar sesi&amp;oacute;n&lt;/a&gt; si lo deseas.";
    } else {
        header( "Location: ".$loginUrl );
    }</pre>
<p>Como de costumbre, vamos a revisarlo:</p>
<ol>
<li>En primer lugar construímos la URL en la que se muestra el <em>diálogo OAuth</em>, generado a partir de unos determinados parámetros:</li>
<ol>
<li>Solicitamos algunos permisos extra: <em>read_stream</em> y <em>friends_interets</em>.</li>
<li>Definimos la URL actual como la dirección a la que debe retornar el <em>diálogo OAuth</em> tras la autorización (o no) del usuario.</li>
</ol>
<li>Ahora seguimos la ejecución. Recuerda que, como hemos definido esta misma URL como dirección de retorno, cuando el usuario autorice (o no) nuestra aplicación, volveremos aquí:</li>
<ol>
<li>Si está presente el parámetro GET &#8216;<em>error</em>&#8216;, significa que el usuario no autorizó la aplicación. En ese caso mostramos un mensaje con una carita triste, y le damos de nuevo la opción de conectar con la aplicación.</li>
<li>En caso contrario, comprobamos si hay algún usuario reconocido. Si así fuera, mostramos un mensaje de bienvenida y un link de <em>logout</em>.</li>
<li>Y si no hubiera ningún usuario reconocido, redirigiríamos automáticamente mediante la función <em>header()</em> a la URL del <em>diálogo OAuth</em> desde la que podrá conectar con la aplicación.</li>
</ol>
</ol>
<h2>5 Resto de métodos</h2>
<p>Lo creas o no, hemos visto prácticamente todos los métodos del PHP SDK. Vamos a revisar los cuatro que nos quedan:</p>
<h3><a href="https://developers.facebook.com/docs/reference/php/facebook-api/">Facebook::api</a></h3>
<p>Método polimórfico que nos permite realizar llamadas al <a href="https://developers.facebook.com/docs/reference/api/">Graph API</a> (incluso con <a href="https://developers.facebook.com/docs/reference/fql/">FQL</a>, el Facebook Query Language). Puede lanzar excepciones de tipo FacebookApiException. Para poder realizar consultas que no sean públicas, debemos asegurarnos previamente de que tenemos permisos suficientes de ese usuario. Puedes probar <a href="http://chusete.es/facebook/phpdemo/api.php">esta demo</a>, de la que tienes a continuación el código:</p>
<pre name="code" class="php">&lt;?php
    require_once("src/facebook.php");

    $config = array(
        'appId' =&gt; '256797284360192',
        'secret' =&gt; '1e4791731181402f02399fbe174cdb0d',
        'fileUpload' =&gt; false, // opcional
    );

    $facebook = new Facebook($config);

    $loginUrl = $facebook-&gt;getLoginUrl();

    $user = $facebook-&gt;getUser();
?&gt;
&lt;html&gt;
    &lt;head&gt;
        &lt;meta charset="UTF-8" /&gt;
    &lt;/head&gt;
    &lt;body&gt;
    &lt;?php
        if($user) {
            try {
                $_SESSION['user_id'] = $user;
                $user_profile = $facebook-&gt;api('/me','GET');
                echo "Nombre: " . $user_profile['name'];
            } catch(FacebookApiException $e) {
                echo "Error. Posiblemente ha expirado la sesión. ";
                echo "&lt;a href='".$loginUrl."'&gt;Volver a iniciar sesión&lt;/a&gt;&lt;br /&gt;";
                $result = $e-&gt;getResult();
                var_dump($result);
            }
        } else {
            echo "Haz clic &lt;a href='".$loginUrl."'&gt;aqu&amp;iacute;&lt;/a&gt; para iniciar sesi&amp;oacute;n";
        }

    ?&gt;
    &lt;/body&gt;
&lt;/html&gt;</pre>
<h3>FacebookApiException</h3>
<p>Cuando realizamos una consulta al API de Facebook mediante Facebook::api, podrán lanzarse excepciones, por lo que cada llamada a Facebook::api deberá ir dentro de su bloque try-catch correspondiente. Las excepciones tendrán estos dos métodos:</p>
<ol>
<li><a href="https://developers.facebook.com/docs/reference/php/exception-getResult/">getResult</a> &#8211; Devuelve un objeto array con el mensaje de error que devuelve el servidor.</li>
<li><a href="https://developers.facebook.com/docs/reference/php/exception-getType/">getType</a> &#8211; Devuelve el tipo de excepción, como por ejemplo <em>OAuthExcepcion</em>.</li>
</ol>
<h3><a href="https://developers.facebook.com/docs/reference/php/facebook-getSignedRequest/">Facebook::getSignedRequest</a></h3>
<p>En la <a href="http://chusete.es/2011/09/22/introduccion-a-la-programacion-en-facebook-iv/">cuarta parte de esta guía</a> vimos qué es el objeto <em><a href="http://developers.facebook.com/docs/authentication/signed_request/">signedRequest</a></em>. Como dijimos, se trata de un objeto que sirve para compartir información entre Facebook y nuestra aplicación. Desde JavaScript no era seguro su uso, ya que, al no deber hacer público el APP_SECRET de una aplicación, no podríamos tener la certeza de que el contenido del objeto <em>signedRequest</em> estuviera realmente firmado por Facebook.</p>
<p>Sin embargo, desde PHP sí podremos, y este método realiza todo el trabajo sucio por nosotros: decodifica, comprueba la firma, y devuelve el objeto en forma de array PHP. De esta forma, con el objeto devuelto por este método podríamos comprobar en una aplicación de tipo <em>Page Tab</em> si el usuario es o no fan (sin necesidad de solicitar ningún permiso).</p>
<p>Consulta la <a href="https://developers.facebook.com/docs/authentication/signed_request/">documentación de signedRequest</a> para más información.</p>
<h3><a href="https://developers.facebook.com/docs/reference/php/facebook-setFileUploadSupport/">Facebook::setFileUploadSupport</a></h3>
<p>Habilita o deshabilita el soporte para subida de ficheros. Éstas se realizarán mediante llamadas al Graph API con el método <strong>Facebook::api</strong> utilizando el método de envío POST. Podemos ver el ejemplo de la documentación de Facebook:</p>
<pre name="code" class="php">$facebook-&gt;setFileUploadSupport(true);

$img = '/tmp/mifoto.png';

$photo = $facebook-&gt;api(
    '/me/photos',
    'POST',
    array(
        'source' =&gt; '@' . $img,
        'message' =&gt; 'Foto subida mediante el SDK de PHP!'
    )
);</pre>
<h3><a href="https://developers.facebook.com/docs/reference/php/facebook-getFileUploadSupport/">Facebook::useFileUploadSupport</a></h3>
<p>Indica si está o no habilitado el soporte para subir ficheros.</p>
<h2>6 Y ahora qué</h2>
<p>Si te has quedado con ganas de más, estás de enhorabuena, porque han quedado muchos conceptos en el tintero.</p>
<p><strong>Otros SDK.</strong> Si tienes pensado desarrollar para Android, puedes echar un vistazo al <a href="https://developers.facebook.com/docs/reference/androidsdk">Android SDK</a>. Puedes hacer también lo propio con el <a href="https://developers.facebook.com/docs/reference/iossdk">iOS SDK</a> si tu intención es crear una aplicación para iPhone o iPad.</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/09/ios4_android.jpg"><img class="aligncenter size-medium wp-image-1230" title="ios4_android" src="http://chusete.es/wp-content/uploads/2011/09/ios4_android-300x175.jpg" alt="" width="300" height="175" /></a></p>
<p><strong>Consultas más eficaces.</strong> Otro asunto interesante por explorar es el <a href="https://developers.facebook.com/docs/reference/fql/">lenguaje FQL</a> para realizar consultas a-la-SQL a Facebook. Mediante este método puedes llevar a cabo comportamientos que con el Graph API no podrías, como ejecutar consultas por lotes.</p>
<p><strong>¡Internacionalizate!</strong> Es otra de las opciones que proporciona Facebook: habilita tu aplicación para que sea traducida, preparándola según las <a href="https://developers.facebook.com/docs/internationalization/">directrices de internacionalización de Facebook</a>.</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/09/i18n_logo.jpg"><img class="aligncenter size-medium wp-image-1231" title="i18n_logo" src="http://chusete.es/wp-content/uploads/2011/09/i18n_logo-300x120.jpg" alt="" width="300" height="120" /></a></p>
<p><strong>Todavía más APIs</strong>&#8230; Tienes a tu alcance <a href="https://developers.facebook.com/docs/reference/ads-api/">Ads API</a>, que te permitirá crear y monitorizar mediante código ambiciosas campañas publicitarias. O <a href="https://developers.facebook.com/docs/creditsapi">Credits API</a>, con la que podrás permitir a tus usuarios comprar créditos de Facebook con los que adquirir nuevas funcionalidades o ítems en tu aplicación. Y <a href="https://developers.facebook.com/docs/chat/">Chat API</a>, con la que podrás incorporar a tu página web, o aplicación nativa, un chat compatible XMPP compatible con Facebook.</p>
<p><strong>Más sobre Graph API</strong>. Si te interesa conocer más acerca de las consultas por lotes, tienes un <a href="https://developers.facebook.com/docs/reference/api/batch/">apartado íntegro</a> dedicado a ellas. Tienes también una <a href="https://developers.facebook.com/docs/reference/api/realtime/">API de actualizaciones en tiempo real</a>.</p>
<p><strong>Juegos</strong>. Lo mencionamos de pasada, pero existe toda una API para que los desarrolladores de videojuegos puedan añadir <a href="https://developers.facebook.com/docs/achievements/">logros</a> y <a href="https://developers.facebook.com/docs/score/">puntuaciones</a>.</p>
<p><strong>Social Design</strong>, es como llaman en Facebook a la forma de pensar cómo crear productos sociales, utilizando tres conceptos clave, comunidad, conversación e identidad. Ver más sobre <a href="https://developers.facebook.com/socialdesign/">Social Design</a>.</p>
<p><strong>Opciones</strong>, muchas más opciones de configuración:</p>
<ul>
<li><strong>Configuración avanzada</strong>:</li>
<ul>
<li>Deauthorize Callback &#8211; Definir una URL a la que se hará un ping cada vez que un usuario se desvincule de tu aplicación (con información en el signedRequest).</li>
<li>Migraciones &#8211; Facebook está en constante cambio. Puedes elegir qué tecnologías usar: las que están en uso o las obsoletas.</li>
<li>Seguridad &#8211; Autorizar determinadas IPs para realizar peticiones en nombre de tu aplicación o para cambiar su configuración. Alertas por email.</li>
<li>Publicidad &#8211; Puedes indicar las direcciones de correo de las cuentas de usuario utilizadas para la publicidad de la página.</li>
<li>Datos de contacto &#8211; Enlaces a las URLs de privacidad, condiciones de uso, de soporte, etc.</li>
</ul>
<li><strong>Roles</strong> &#8211; Desde donde podrás añadir otros usuarios a diferentes perfiles: Desarrollador, tester, usuarios de pruebas (usuarios falsos creados al vuelo), etc.</li>
<li><strong>Credits</strong> &#8211; Donde personalizas los parámetros de configuración necesarios para poder operar con créditos Facebook.</li>
</ul>
<p><strong>Nueva versión de Open Graph</strong>: Hasta ahora podía establecerse un vínculo entre un usuario y otro objeto con el verbo &#8220;me gusta&#8221;. Por ejemplo, &#8220;<em>A Pedro le gusta Coca-Cola</em>&#8220;. Tenemos un <span style="text-decoration: underline;">sujeto</span> (Pedro), una <span style="text-decoration: underline;">acción</span> (gustar), y un <span style="text-decoration: underline;">objeto</span> (Coca-Cola). Hasta ahora el verbo era siempre &#8220;gustar&#8221;. Sin embargo, con esta nueva versión, podrá ser cualquier cualquier cosa: &#8220;<em>María ha tomado un Big Mac</em>&#8220;. Puedes seguir este <a href="https://developers.facebook.com/docs/beta/opengraph/tutorial/">tutorial paso a paso</a>.</p>
<h2><a href="http://chusete.es/wp-content/uploads/2011/09/attachment.jpeg"><img class="aligncenter size-medium wp-image-1232" title="Facebook Open Graph" src="http://chusete.es/wp-content/uploads/2011/09/attachment-300x112.jpg" alt="" width="300" height="112" /></a>7 Resumen</h2>
<p>Con suerte, habrás llegado hasta aquí. Eso significa que ya ha finalizado tu toma de contacto con el desarrollo de aplicaciones en Facebook. Dominas tecnologías básicas como los <strong>social plugins</strong>, <strong>open graph</strong>, o los <strong>diálogos</strong>. Sabes crear distintos tipos de aplicaciones, ya sea en una <strong>web externa</strong>, en un <strong>Canvas</strong>, o en un <strong>Page Tab</strong>. Conoces a fondo el <strong>JavaScript SDK</strong> y el <strong>PHP SDK</strong>. Has tenido una toma de contacto con el <strong>Graph API</strong>. Sabes <strong>autenticar y solicitar permisos</strong> a tus usuarios en cualquier escenario. Eres consciente del <strong>resto de tecnologías de Facebook</strong> que tienes a tu alcance. Sabes qué son los <strong>Social Channels</strong>, y cómo aprovecharlos para dar mayor visibilidad a tus aplicaciones. No está nada mal, ¿no?</p>
<p>Espero que hayas disfrutado de estos artículos tanto como yo, y ojalá puedan serte de utilidad.</p>
<p><strong>¡Muchas gracias por haber seguido esta guía!</strong>.
<div class="tweetmeme_button" style="float: left; margin-right: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fchusete.es%2F2011%2F09%2F23%2Fintroduccion-a-la-programacion-en-facebook-v%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fchusete.es%2F2011%2F09%2F23%2Fintroduccion-a-la-programacion-en-facebook-v%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/09/23/introduccion-a-la-programacion-en-facebook-v/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>Introducción a la programación en Facebook</title>
		<link>http://chusete.es/2011/09/13/introduccion-a-la-programacion-en-facebook/</link>
		<comments>http://chusete.es/2011/09/13/introduccion-a-la-programacion-en-facebook/#comments</comments>
		<pubDate>Tue, 13 Sep 2011 00:09:47 +0000</pubDate>
		<dc:creator>chusete</dc:creator>
				<category><![CDATA[desarrollo]]></category>
		<category><![CDATA[javasctipt]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[API Graph]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[facebook API]]></category>
		<category><![CDATA[open graph]]></category>

		<guid isPermaLink="false">http://chusete.es/?p=1091</guid>
		<description><![CDATA[¿De modo que te han pedido que hagas una aplicación para Facebook y no sabes por dónde empezar? ¿Has llegado a la documentación oficial y te pierdes entre tanto Open Graph, SDK, plugins, dialogs y Graph API? Don&#8217;t panic! En este artículo vamos a ver paso a paso cómo empezar a programar en el nuevo sistema [...]]]></description>
			<content:encoded><![CDATA[<p><img class="aligncenter size-full wp-image-1129" title="head_fb1" src="http://chusete.es/wp-content/uploads/2011/09/head_fb1.jpg" alt="" width="100%" /></p>
<p>¿De modo que te han pedido que hagas una aplicación para Facebook y no sabes por dónde empezar? ¿Has llegado a la <a href="https://developers.facebook.com/docs/">documentación oficial</a> y te pierdes entre tanto Open Graph, SDK, plugins, dialogs y Graph API? Don&#8217;t panic! En este artículo vamos a ver paso a paso cómo empezar a programar en el nuevo sistema de Facebook. ¡Al lío!</p>
<p><span id="more-1091"></span></p>
<h2>Tipos de aplicaciones</h2>
<p>En el apartado <em><a href="http://developers.facebook.com/docs/">Getting Started</a></em> de la documentación oficial vemos que nos dan tres opciones:</p>
<ol>
<li><strong><a href="https://developers.facebook.com/docs/guides/web/">Páginas web</a></strong>. Para crear una aplicación que se ejecute en tu página web fuera de Facebook.</li>
<li><strong><a href="https://developers.facebook.com/docs/guides/mobile/">Aplicaciones móviles</a></strong>. Para crear apps para las principales infraestructuras móviles.</li>
<li><strong><a href="https://developers.facebook.com/docs/guides/canvas/">Aplicaciones en Facebook</a></strong>. Este decir, para crear una aplicación que se insertará dentro de la web de Facebook, en un <strong>canvas</strong>.</li>
</ol>
<p>En cualquiera de los tres casos, las tecnologías que utilizaremos serían básicamente las mismas.</p>
<p>Más adelante revisaremos algunas de las tecnologías que nos ofrece Facebook para integrar nuestra aplicación con su infraestructura.</p>
<div class="note">
<h3>Aplicaciones de Escritorio</h3>
<p>Existe un cuarto tipo de aplicaciones, que no se mencionan, y que pueden comunicarse con Facebook: Aplicaciones de escritorio. En esta guía no lo abordaremos.</p>
</div>
<p>Además, en la página de inicio ofrecen un <a href="https://developers.facebook.com/docs/samples/">apartado de ejemplos</a> donde podrás probar y descargar distintas demos, como el de una aplicación en página web, o una aplicación dentro de un canvas en Facebook. También puedes acceder a <a href="https://developers.facebook.com/videos/">vídeos</a> con charlas y guías.</p>
<h2>Dando de alta una aplicación</h2>
<p>Para entender mejor todos los apartados, y para poder realizar algunos ejemplos, vamos a crearnos una nueva aplicación. Para ello, vamos a seguir los siguientes pasos:</p>
<p>Accedemos a la página de desarrolladores de Facebook: <a href="https://developers.facebook.com/">https://developers.facebook.com/</a></p>
<p><a href="https://developers.facebook.com/"></a>Una vez ahí, seleccionamos &#8220;<a href="https://developers.facebook.com/apps">Aplicaciones</a>&#8221; en el menú.</p>
<p>En tercer lugar, pulsamos sobre el botón <a href="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-12-a-las-23.10.39.png"><img class="alignnone size-full wp-image-1110" title="Captura de pantalla 2011-09-12 a la(s) 23.10.39" src="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-12-a-las-23.10.39.png" alt="" width="120" height="24" /></a>.</p>
<p>Ahora indicamos un nombre y la local de la aplicación y pulsamos <em>Continuar</em>:</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-12-a-las-23.11.27.png"><img class="aligncenter size-medium wp-image-1111" title="Captura de pantalla 2011-09-12 a la(s) 23.11.27" src="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-12-a-las-23.11.27-300x109.png" alt="" width="300" height="109" /></a></p>
<p>Completamos el captcha y pulsamos sobre <em>Enviar:</em></p>
<p><em><a href="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-12-a-las-23.12.48.png"><img class="aligncenter size-medium wp-image-1112" title="Captura de pantalla 2011-09-12 a la(s) 23.12.48" src="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-12-a-las-23.12.48-300x127.png" alt="" width="300" height="127" /></a></em></p>
<p>Y con esto ya estaría dada de alta nuestra aplicación:</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-12-a-las-23.14.33.png"><img class="aligncenter size-medium wp-image-1113" title="Captura de pantalla 2011-09-12 a la(s) 23.14.33" src="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-12-a-las-23.14.33-300x252.png" alt="" width="300" height="252" /></a></p>
<p>Fíjate en la caja superior. Verás dos campos: App ID y App Secret. Estos código los necesitarás para hacer funcionar tu aplicación. El primero es el código que identifica la app, y el segundo es un código de seguridad que utilizarás para la autenticación en el lado del servidor.</p>
<p>Por lo pronto, podemos cambiar los siguientes campos:</p>
<ul>
<li><strong>Logo</strong>. Corresponde al logo de 75&#215;75 px de la aplicación.</li>
<li><strong>Icono</strong>. Icono de 16&#215;16 px de la aplicación</li>
<li><strong>App Secret</strong>. Este código no debemos compartirlo con nadie. Desde este apartado podremos reiniciarlo si lo deseáramos.</li>
<li><strong>App Display Name.</strong> Nombre con el que se mostrará la aplicación.</li>
<li><strong>App Namespace.</strong> Nombre del espacio de nombres de la aplicación, formado únicamente por caracteres en minúsculas, guiones medios y guiones bajos.</li>
<li><strong>Contact Email.</strong> Dirección de correo electrónico de contacto.</li>
<li><strong>App Domain.</strong> Dominio sobre el que se alojará la aplicación (por ejemplo www.example.com).</li>
<li><strong>Category</strong> y <strong>Sub-category.</strong> Categorías en las que catalogamos la aplicación.</li>
</ul>
<p>Además, vemos que podemos definir 4 formas distintas de integrar la aplicación con Facebook:</p>
<ol>
<li><strong>Website.</strong> Para cuando queramos que en nuestra página puedan los usuarios hacer login con su cuenta de Facebook.</li>
<li><strong>App on Facebook.</strong> Aplicación para incorporar en un canvas dentro de Facebook.</li>
<li><strong>Mobile Native.</strong> Para crear una aplicación para móviles.</li>
<li><strong>Page Tab.</strong> Permite crear una aplicación que se mostrará como una pestaña dentro de una Facebook Page.</li>
</ol>
<p>Y estas son todas las opciones básicas que tenemos disponibles para configurar una aplicación de Facebook. Sin embargo, podemos acceder a la configuración avanzada desde el menú de la izquierda, pulsando sobre <em>Configuration &gt; Advanced</em>:</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/09/Advanced-Desarrolladores-de-Facebook.png"><img class="aligncenter size-medium wp-image-1114" title="Advanced - Desarrolladores de Facebook" src="http://chusete.es/wp-content/uploads/2011/09/Advanced-Desarrolladores-de-Facebook-188x300.png" alt="" width="188" height="300" /></a></p>
<p>En este apartado avanzado por ahora podremos establecer la descripción de nuestra aplicación, y el <em>Sandbox Mode</em> (habilitado indica que sólo los desarrolladores pueden acceder a la aplicación).</p>
<p>Rápido e indoloro, ya tenemos nuestra aplicación creada <img src='http://chusete.es/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . Cada vez que queramos volver a la configuración de nuestra aplicación, tan solo tendremos que acceder a la página de desarrolladores de Facebook, apartado <a href="https://developers.facebook.com/apps">Aplicaciones</a>, y seleccionamos la opción deseada.</p>
<div class="note">
<h3>Página dentro de Facebook</h3>
<p>Si quisiéramos acceder a la página de la aplicación (su página dentro de Facebook, no su perfil de configuración), desde su pantalla de configuración, en el menú izquierda, pulsamos sobre <em>View App Profile Page</em>. Veremos una página en blanco esperando a ser completada:</p>
<p style="text-align: center;"><a href="http://chusete.es/wp-content/uploads/2011/09/chusete-demo.png"><img class="size-medium wp-image-1117 aligncenter" title="chusete demo" src="http://chusete.es/wp-content/uploads/2011/09/chusete-demo-192x300.png" alt="" width="192" height="300" /></a></p>
<p style="text-align: left;">Podremos completar la página de perfil de la aplicación en cualquier momento.</p>
</div>
<h2>Tecnologías disponibles</h2>
<p>Bien, y ¿qué tecnologías nos ofrece Facebook para implementar una aplicación? Éstas son las principales:</p>
<h3>1. <a href="https://developers.facebook.com/docs/plugins/">Social plugins</a></h3>
<p>Corresponde a pequeños plugins o <em>widgets</em> que se pueden incorporar muy fácilmente en cualquier página web ajena a Facebook. Accediendo a la página de cada uno de ellos verás un pequeño formulario que te genera el código necesario para que lo incorpores en tu página. Seguro que estás muy familiarizado con casi todos ellos:</p>
<div style="overflow: hidden; margin-top: 10px;"><img class="alignleft size-full wp-image-1093" style="margin-right: 10px;" title="like" src="http://chusete.es/wp-content/uploads/2011/09/like.png" alt="" width="128" height="88" /><strong><a href="https://developers.facebook.com/docs/reference/plugins/like">Botón &#8220;Me gusta&#8221;.</a></strong><br />
Es el más famoso de todos los plugins. Permite a los usuarios compartir con un solo clic la página que están visitando</div>
<div style="overflow: hidden; margin-top: 10px;"><img class="alignleft size-full wp-image-1094" style="margin-right: 10px;" title="send" src="http://chusete.es/wp-content/uploads/2011/09/send.png" alt="" width="128" height="88" /><strong><a href="https://developers.facebook.com/docs/reference/plugins/send">Botón &#8220;Enviar&#8221;.</a></strong><br />
Permite que los usuarios envíen a alguno/s de sus contactos la página que están visitando.</div>
<div style="overflow: hidden; margin-top: 10px;"><img class="alignleft size-full wp-image-1095" style="margin-right: 10px;" title="comments" src="http://chusete.es/wp-content/uploads/2011/09/comments-1.png" alt="" width="128" height="88" /><strong><a href="https://developers.facebook.com/docs/reference/plugins/comments"> Comentarios.</a></strong><br />
Para añadir un sistema de comentarios a tu página web.</div>
<div style="overflow: hidden; margin-top: 10px;"><img class="alignleft size-full wp-image-1096" style="margin-right: 10px;" title="activityfeed" src="http://chusete.es/wp-content/uploads/2011/09/activityfeed.png" alt="" width="128" height="88" /><strong><a href="https://developers.facebook.com/docs/reference/plugins/activity">Feed de actividades.</a></strong><br />
Muestra una lista de las últimas actividades que han llevado a cabo tus contactos de Facebook.</div>
<div style="overflow: hidden; margin-top: 10px;"><img class="alignleft size-full wp-image-1097" style="margin-right: 10px;" title="recommendations" src="http://chusete.es/wp-content/uploads/2011/09/recommendations.png" alt="" width="128" height="88" /><strong><a href="https://developers.facebook.com/docs/reference/plugins/recommendations">Recomendaciones.</a></strong><br />
Muestra al usuario una lista personalizada de enlaces recomendados, en función de diferentes parámetros, como por ejemplo las preferencias de sus amigos.</div>
<div style="overflow: hidden; margin-top: 10px;"><img class="alignleft size-full wp-image-1098" style="margin-right: 10px;" title="likebox" src="http://chusete.es/wp-content/uploads/2011/09/likebox.png" alt="" width="128" height="88" /><strong><a href="https://developers.facebook.com/docs/reference/plugins/like-box">Caja &#8220;me gusta&#8221;.</a></strong><br />
Similar al botón &#8220;Me gusta&#8221;, pero con más elementos. Por ejemplo, muestra las últimas actividades de la página, o una lista de personas a las que les gusta.</div>
<div style="overflow: hidden; margin-top: 10px;"><img class="alignleft size-full wp-image-1099" style="margin-right: 10px;" title="login" src="http://chusete.es/wp-content/uploads/2011/09/login.png" alt="" width="128" height="88" /><strong><a href="https://developers.facebook.com/docs/reference/plugins/login">Botón &#8220;Login&#8221;.</a></strong><br />
Botón que permite iniciar sesión en la página utilizando la infraestructura de sesiones de Facebook.</div>
<div style="overflow: hidden; margin-top: 10px;"><img class="alignleft size-full wp-image-1100" style="margin-right: 10px;" title="register" src="http://chusete.es/wp-content/uploads/2011/09/register.png" alt="" width="128" height="88" /><strong><a href="https://developers.facebook.com/docs/plugins/registration">Registro.</a></strong><br />
Formulario de registro a una página que se rellena automáticamente con tus datos de Facebook. De este modo, se ahorra tiempo a los usuarios.</div>
<div style="overflow: hidden; margin-top: 10px;"><img class="alignleft size-full wp-image-1101" style="margin-right: 10px;" title="facepile" src="http://chusete.es/wp-content/uploads/2011/09/facepile.png" alt="" width="128" height="88" /><strong><a href="https://developers.facebook.com/docs/reference/plugins/facepile">Facepile.</a></strong><br />
Muestra una lista de imágenes de perfil de los usuarios a los que les ha gustado la página que se está visitando.</div>
<div style="overflow: hidden; margin-top: 10px;"><img class="alignleft size-full wp-image-1102" style="margin-right: 10px;" title="livestream" src="http://chusete.es/wp-content/uploads/2011/09/livestream.png" alt="" width="128" height="88" /><strong><a href="https://developers.facebook.com/docs/reference/plugins/live-stream">Live Stream.</a></strong><br />
Muestra un pequeño &#8216;chat&#8217; vinculado a la página que se está visitando.</div>
<p>Como ves, a base de insertar este tipo de plugins, puedes crear una página web muy rica en funcionalidades en un tiempo récord. A modo de demostración, <a href="http://www.myfbse.com/winery/storybar.html">puedes consultar esta página</a>, que forma parte del apartado de ejemplos de Facebook. Esta demo hace uso del <em>botón &#8220;me gusta&#8221;</em>, del <em>feed de actividades</em>, de las <em>recomendaciones</em> y de los <em>comentarios</em>.</p>
<h3>2. <a href="https://developers.facebook.com/docs/reference/dialogs/">Diálogos</a></h3>
<p>Podemos definir los diálogos como ventanas emergentes que solicitan al usuario permiso para realizar alguna acción.</p>
<div class="note"><strong>Autorizaciones</strong><br />
Más adelante veremos que si, por ejemplo, quisiéramos que nuestra aplicación publicara una entrada en el muro de un usuario, necesitaríamos que éste nos hubiera concedido previamente permisos para realizar esta acción. Con los diálogos esto no es necesario, ya que por definición un diálogo necesita que el usuario lo autorice para realizar cualquier acción.</div>
<p>Podemos invocar los diálogos a mano, sin embargo en general suele ser mucho más cómo realizarlo mediante alguno de los SDK que Facebook nos ofrece. En concreto, para páginas web, utilizaremos el <a href="https://developers.facebook.com/docs/reference/javascript/">SDK JavaScript</a> mediante el método <a href="https://developers.facebook.com/docs/reference/javascript/FB.ui">FB.ui</a>. En el apartado del SDK de JavaScript veremos cómo invocar estos diálogos.</p>
<p>Por lo pronto, vamos a ver cuáles son los distintos diálogos que nos ofrece Facebook:</p>
<p><strong>Diálogo de Feed</strong></p>
<p>Permite al usuario añadir a su muro, desde nuestra aplicación, una publicación.</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/09/Facebook_Dialogs_Feed_Iframe.png"><img class="aligncenter size-medium wp-image-1104" title="Facebook_Dialogs_Feed_Iframe" src="http://chusete.es/wp-content/uploads/2011/09/Facebook_Dialogs_Feed_Iframe-300x170.png" alt="" width="300" height="170" /></a><strong>Diálogo de amigos</strong></p>
<p>Muestra un diálogo para añadir a un amigo.</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/09/friends-dialog2.png"><img class="aligncenter size-medium wp-image-1105" title="friends-dialog2" src="http://chusete.es/wp-content/uploads/2011/09/friends-dialog2-300x117.png" alt="" width="300" height="117" /></a></p>
<p><strong>Diálogo OAuth</strong></p>
<p>Solicita al usuario unas determinadas autorizaciones, y concede permisos a la aplicación.</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/09/oauth-page.png"><img class="aligncenter size-medium wp-image-1106" title="oauth-page" src="http://chusete.es/wp-content/uploads/2011/09/oauth-page-300x201.png" alt="" width="300" height="201" /></a></p>
<p><strong>Diálogo de Pago</strong></p>
<p>Permite al usuario adquirir nuevos créditos de Facebook.</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/09/2vsp2jb.png"><img class="aligncenter size-medium wp-image-1107" title="2vsp2jb" src="http://chusete.es/wp-content/uploads/2011/09/2vsp2jb-300x171.png" alt="" width="300" height="171" /></a><strong>Diálogo de petición</strong></p>
<p>Diálogo que permite al usuario enviar una petición a uno o más amigos.</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/09/165306_796701067511_703_41122128_101111_n.jpg"><img class="aligncenter size-medium wp-image-1108" title="165306_796701067511_703_41122128_101111_n" src="http://chusete.es/wp-content/uploads/2011/09/165306_796701067511_703_41122128_101111_n-300x277.jpg" alt="" width="300" height="277" /></a></p>
<p><strong>Diálogo de envío</strong></p>
<p>Diálogo para que el usuario envíe un mensaje a algún amigo, a un grupo de amigos, o a una dirección de correo.</p>
<h3><a href="http://chusete.es/wp-content/uploads/2011/09/Facebook_Dialogs_Send.png"><img class="aligncenter size-medium wp-image-1109" title="Facebook_Dialogs_Send" src="http://chusete.es/wp-content/uploads/2011/09/Facebook_Dialogs_Send-300x156.png" alt="" width="300" height="156" /></a>3. <a href="http://developers.facebook.com/docs/authentication/">Autenticación</a> y Permisos</h3>
<p>A menudo necesitaremos que los usuarios nos autoricen a acceder a su información. Por ejemplo, cuando queramos que puedan iniciar sesión en nuestra web utilizando su cuenta de Facebook, o cuando desde nuestra aplicación queramos acceder a determinados campos de su perfil de usuario. Para solicitar esta autorización utilizaremos el Diálogo OAuth.</p>
<p>Cada vez que se utiliza el diálogo OAuth, podremos pasarle información al diálogo acerca de la los permisos de acceso que autorizará el usuario. Te recomiendo que revises la <a href="http://developers.facebook.com/docs/reference/api/permissions/">lista de todos los posibles permisos</a>. Además, ten en cuenta que cuantos más permisos solicites a un usuario, menor será el número de personas que decidan autorizar a tu aplicación.</p>
<p>Existen dos métodos posibles de autenticación: Desde el servidor, o desde el cliente. Pero, para simplificar, podemos decir que son equivalentes el uno al otro.</p>
<h3>4. <a href="http://developers.facebook.com/docs/reference/api">Graph API</a></h3>
<p>El nucleo de Facebook es un grafo social, donde cada persona, foto, evento o página tiene su ID único, y donde existen conexiones entre todos ellos (por ejemplo, amistades, etiquetas en fotos, contenidos compartidos, etc.).</p>
<p>Para acceder a las propiedades de cualquiera de estos objetos accederemos a la URL: <strong>https://graph.facebook.com/ID</strong> cambiando ID por el identificador del objeto que queramos consultar. Como resultado, nos devolverá un objeto JSON.</p>
<p>Por ejemplo, al comienzo de este artículo creamos una aplicación. Puedes coger el App ID de tu aplicación y acceder a su información. Te saldrá algo similar a esto:</p>
<pre name="code" class="javascript">{
   "id": "256797284360192",
   "name": "chusete demo",
   "description": "Aplicaci\u00f3n de pruebas de Chusete",
   "category": "Utilities",
   "subcategory": "News",
   "link": "http://www.facebook.com/apps/application.php?id=256797284360192"
}</pre>
<p>En el caso de los usuarios y de las páginas, cuando tengan un alias, se podrá usar como alternativa al ID.</p>
<p>Por supuesto, todas estas peticiones devuelven por defecto tan solo la información pública de ese objeto/persona. Para acceder a información privada, debemos contar con su autorización. Esta autorización se proporciona mediante el parámetro GET access_token.</p>
<div class="note">
<h3>Graph API Explorer</h3>
<p>Lo mejor para aprender más sobre Graph API es utilizar la herramienta Graph API Explorer, un sencillo explorador para comprobar el resultado de todas las posibles consultas que podemos realizar: <a href="http://developers.facebook.com/tools/explorer">http://developers.facebook.com/tools/explorer</a>. Vamos a ver cómo se usa:</p>
<p>En primer lugar, debemos establecer los permisos que le otorgamos a la herramienta. Para ello pulsamos sobre el botón Get Access Token, donde se desplegarán casillas con todos los posibles permisos (tal como vimos en el apartado anterior, sobre Autenticación). Una vez establecidos, podemos realizar las consulta que queramos desde la columna derecha <em>Conexiones</em>:</p>
<p><a href="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-13-a-las-00.50.30.png"><img class="aligncenter size-full wp-image-1118" title="Captura de pantalla 2011-09-13 a la(s) 00.50.30" src="http://chusete.es/wp-content/uploads/2011/09/Captura-de-pantalla-2011-09-13-a-las-00.50.30.png" alt="" width="245" height="197" /></a></p>
<p>En resumen, en esta utilidad veremos lo siguiente:</p>
<ul>
<li><strong>Access Token</strong> &#8211; Es el parámetro access_token que se proporciona en cada petición al Graph API.</li>
<li><strong>Tipo de petición</strong> &#8211; Es un campo desplegable. Por defecto tendrá el valor GET.</li>
<li><strong>URL de petición</strong> &#8211; Corresponde a la URL sobre la que se realiza la petición.</li>
<li><strong>Resultado</strong> &#8211; Es el bloque gris sobre el que se muestra el resultado JSON.</li>
<li><strong>Conexiones</strong> &#8211; Son enlaces a distintas conexiones sobre el objeto actual.</li>
<li><strong>Fields</strong> &#8211; Campos que muestra el objeto JSON para la petición actual. No tienen por qué mostrarse todos.</li>
</ul>
</div>
<h3>5. <a href="http://developers.facebook.com/docs/opengraph/">Open Graph Protocol</a></h3>
<p><a href="http://chusete.es/wp-content/uploads/2011/09/open_graph_protocol_logo.png"><img class="alignleft size-medium wp-image-1116" title="open_graph_protocol_logo" src="http://chusete.es/wp-content/uploads/2011/09/open_graph_protocol_logo-300x300.png" alt="" width="300" height="300" /></a>Esto no es una tecnología del core de Facebook propiamente dicha, pero sí es algo sobre lo que se apoya. ¿De qué se trata? Voy a explicarlo mediante un ejemplo. Supón que creas una página web de restaurantes, donde cada uno tiene su propia URL. Un día un usuario comparte esta URL en Facebook. ¿Qué ocurrirá? Que Facebook elegirá la información y las imágenes que él considere relevante. Pero, ¿y si quisiéramos nosotros decirle a Facebook (y otras redes sociales) la información que debe mostrar? Para dar respuesta a eso surge el protocolo Open Graph.</p>
<p>En otras palabras: Hace que nuestras páginas web se conviertan en objetos &#8220;del mundo real&#8221; con el que pueden interactuar las redes sociales. Películas, restaurantes, celebridades, etc.</p>
<p>En el caso concreto de Facebook, además, cuando un usuario haga clic en el plugin del botón &#8220;Me gusta&#8221; de una de tus páginas, será equivalente a que hiciera clic en &#8220;Me gusta&#8221; de alguna de las Facebook Pages, por lo que podrás enviarle actualizaciones a su Feed. Mola, ¿no?</p>
<p>Su funcionamiento no podría ser más sencillo. Open Graph Protocol está basado en <a href="http://es.wikipedia.org/wiki/RDFa">RDFa</a>, por lo que mediante etiquetas meta puedes añadir semántica a tus páginas. Además, para una correcta integración con Facebook, debes añadir el plugin del botón &#8220;Me gusta&#8221;.</p>
<p>Para más información, revisa la página oficial de Open Graph Protocol: <a href="http://ogp.me/">http://ogp.me/</a></p>
<h3>6. Otras tecnologías</h3>
<p>Además de todas las tecnologías que hemos visto, existen otras de tipo <em>avanzado</em> que, por lo general, no será necesario usarlas. En concreto estaríamos hablando de:</p>
<ul>
<li><strong><a href="http://developers.facebook.com/docs/reference/fql">FQL</a></strong>. Facebook Query Language, o Lenguaje de consultas de Facebook. Similar a SQL, sirve para consultar los datos que ofrece Graph API.</li>
<li><strong><a href="http://developers.facebook.com/docs/internationalization">API de internacionalización</a></strong>. Mediante esta API puedes aprovechar la infraestructura de internacionalización de Facebook para tu aplicación.</li>
<li><strong><a href="http://developers.facebook.com/docs/creditsapi">API de créditos</a></strong>. Para que los usuarios puedan realizar pagos de créditos de Facebook para utilizar en tu aplicación.</li>
<li><strong><a href="http://developers.facebook.com/docs/reference/ads-api">API de publicidad</a></strong>. Permite crear y gestionar mediante código tus campañas publicitarias.</li>
<li><strong><a href="http://developers.facebook.com/docs/chat">API de Chat</a></strong>. Para aquellos desarrolladores que quieran integrar el chat de Facebook en sus aplicaciones, mediante el protocolo estándar <a href="http://es.wikipedia.org/wiki/Extensible_Messaging_and_Presence_Protocol">Jabber/XMPP</a>.</li>
</ul>
<p><strong>APIs obsoletas</strong>. Además, existen determinadas APIs que han quedado obsoletas y a las que pronto Facebook dejará de dar soporte, como la API REST, el lenguaje de marcado FBML, o la API JavaScript.</p>
<h2>SDKs</h2>
<p>Por último, vamos a repasar los distintos kits de desarrollo que nos regala Facebook. Cabe destacar que no es imprescindible utilizarlos, ya que podremos realizar la autenticación, invocación de diálogos, o las llamadas a la API a mano. Pero, como podrás imaginar, resulta mucho más sencillo utilizar una herramienta ya probada que lo haga por nosotros.</p>
<p>Existen cuatro SDKs:</p>
<ol>
<li><a href="http://developers.facebook.com/docs/reference/javascript/">JavaScript SDK</a>.</li>
<li><a href="http://github.com/facebook/php-sdk/">PHP SDK</a>.</li>
<li><a href="http://developers.facebook.com/docs/reference/ios">iOS SDK (iPhone &amp; iPad)</a>.</li>
<li><a href="http://developers.facebook.com/docs/reference/android">Android SDK</a>.</li>
</ol>
<p>Aquí vamos a hablar de los dos primeros.</p>
<h3>1. JavaScript SDK</h3>
<p>Permite realizar llamadas a la Graph API, crear diálogos, renderizar los Social Plugins, además de otras muchas cosas. Para usar el SDK, debemos  intrducir el siguiente código a nuestra aplicación:</p>
<pre name="code" class="javascript">&lt;div id="fb-root"&gt;&lt;/div&gt;
&lt;script src="http://connect.facebook.net/en_US/all.js"&gt;&lt;/script&gt;
&lt;script&gt;
  FB.init({
    appId  : 'ID DE TU APP',
    status : true, // comprobar estado de login
    cookie : true, // habilitar cookies para permitir al servidor acceder a la sesión
    xfbml  : true, // ejecutar código XFBML
    channelURL : 'http://WWW.MIDOMINIO.COM/channel.html', // fichero channel.html
    oauth  : true // habilita OAuth 2.0
  });
&lt;/script&gt;</pre>
<p>Y en el fichero channel.html añades el siguiente contenido:</p>
<pre name="code" class="javascript">&lt;script src="http://connect.facebook.net/en_US/all.js"&gt;&lt;/script&gt;</pre>
<p>Y ya lo tienes. Tu página está preparada para ejecutar código del SDK JavaScript de Facebook.</p>
<div class="note">
<h3>JavaScript Test Console</h3>
<p>Del mismo modo que teníamos una herramienta para poder probar la Graph API, también tenemos una <a href="http://developers.facebook.com/tools/console/">consola de desarrollo para el SDK de JavaSript</a>. Para ello, accedemos a <a href="http://developers.facebook.com/tools/console/">http://developers.facebook.com/tools/console/</a> pulsamos sobre Login para concederle permisos a la aplicación de la consola de desarrollo, introducimos el código JavaScript que queremos probar, y pulsamos sobre &#8220;Run Code&#8221;.</p>
<p>Para hacer las cosas más fáciles, podemos pulsar sobre el botón &#8220;Examples&#8221; al pie del textarea, y seleccionamos el ejemplo que deseamos probar.</p>
</div>
<h3>2. PHP SDK</h3>
<p>El SDK oficial para PHP de Facebook es un proyecto open source que se encuentra alojado en GitHub:  <a href="https://github.com/facebook/php-sdk/">https://github.com/facebook/php-sdk/</a>.</p>
<p>Si bien existe un <a href="https://github.com/facebook/php-sdk/blob/master/examples/example.php">ejemplo básico</a>, pero completo, sobre su uso, vamos a resumir aquí las principales operaciones:</p>
<p>Código de inicialización:</p>
<pre name="code" class="php">require 'php-sdk/src/facebook.php';

$facebook = new Facebook(array(
  'appId'  =&gt; 'TU_APP_ID',
  'secret' =&gt; 'TU_APP_SECRET',
));

// Obtener ID de usuario
$user = $facebook-&gt;getUser();</pre>
<p>Llamada a la API (Graph API):</p>
<pre name="code" class="php">if ($user) {
  try {
    // Procedemos sabiendo que tenemos un usuario que ha iniciado sesión y concedido permisos.
    $user_profile = $facebook-&gt;api('/me');
  } catch (FacebookApiException $e) {
    error_log($e);
    $user = null;
  }
}</pre>
<p>Obtener URLs de inicio de sesión y de salida:</p>
<pre name="code" class="php">if ($user) {
  $logoutUrl = $facebook-&gt;getLogoutUrl();
} else {
  $loginUrl = $facebook-&gt;getLoginUrl();
}</pre>
<h2>Resumen</h2>
<p>Este ha sido un post bastante extenso, al que le seguirán otros con distintos casos de uso. Por lo pronto, hemos visto que es posible implementar distintos tipos de aplicaciones para Facebook: para el móvil, para una página web, y empotradas en Facebook. Hemos revisado paso a paso el proceso de alta de una nueva aplicación, donde establecemos los parámetros básicos, el nombre, logo, descripción, etc. También hemos revisado todas las tecnologías que nos ofrece Facebook para desarrollar aplicaciones en su ecosistema: Social Plugins, Diálogos, Autenticación y permisos, Graph API y Open Graph. Por último, hemos repasado las distintas bibliotecas que nos da Facebook para facilitar el desarrollo de aplicaciones en JavaScript, PHP, iOS y Android, centrándonos en las dos primeras.</p>
<p>Ahora que conocemos bien todo marco de trabajo sobre el que se apoyan las aplicaciones en Facebook, estamos listos para comenzar. En el siguiente post realizaremos una pequeña aplicación que sirva como demo de todos estos conceptos.
<div class="tweetmeme_button" style="float: left; margin-right: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fchusete.es%2F2011%2F09%2F13%2Fintroduccion-a-la-programacion-en-facebook%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fchusete.es%2F2011%2F09%2F13%2Fintroduccion-a-la-programacion-en-facebook%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/09/13/introduccion-a-la-programacion-en-facebook/feed/</wfw:commentRss>
		<slash:comments>15</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>9</slash:comments>
		</item>
		<item>
		<title>Limitar la velocidad de descarga en PHP</title>
		<link>http://chusete.es/2010/09/28/limitar-la-velocidad-de-descarga-en-php/</link>
		<comments>http://chusete.es/2010/09/28/limitar-la-velocidad-de-descarga-en-php/#comments</comments>
		<pubDate>Mon, 27 Sep 2010 23:08:18 +0000</pubDate>
		<dc:creator>chusete</dc:creator>
				<category><![CDATA[php]]></category>
		<category><![CDATA[descarga]]></category>
		<category><![CDATA[límite]]></category>
		<category><![CDATA[velocidad]]></category>

		<guid isPermaLink="false">http://chusete.es/?p=861</guid>
		<description><![CDATA[Una de las cosas que tienen muchas páginas de descarga directa es la velocidad limitada para los clientes no premium. ¿Cómo lo hacen? Vamos cómo. En este ejemplo vamos a suponer que queremos limitar la velocidad de descarga a 5kB/s. Para ello utilizaremos la extensión HTTP de pecl, en concreto la magia reside en la [...]]]></description>
			<content:encoded><![CDATA[<p>Una de las cosas que tienen muchas páginas de descarga directa es la velocidad limitada para los clientes no premium. ¿Cómo lo hacen? Vamos cómo.</p>
<p>En este ejemplo vamos a suponer que queremos limitar la velocidad de descarga a 5kB/s. Para ello utilizaremos la extensión <a href="http://www.php.net/manual/es/book.http.php">HTTP de pecl</a>, en concreto la <em>magia</em> reside en la función <a href="http://www.php.net/manual/es/function.http-throttle.php">http_throttle</a>. Esta función recibe dos parámetros:</p>
<ol>
<li>número de segundos entre cada envío de bloques de datos.</li>
<li>tamaño en bytes de cada bloque de datos.</li>
</ol>
<p>De este modo, si le decimos que cada bloque de datos tenga un tamaño de 5000 bytes, y que entre cada petición debe transcurrir un segundo, conseguiremos que las descargas se realicen a 5kB/s. Realmente no es una velocidad estable, pero tiene muy pocas oscilaciones, la mayoría debidas a la conexión más que al servidor. Este es el código de ejemplo:</p>
<pre>
<div id="_mcePaste">&lt;?php
   http_throttle(1, 5000);
   http_send_content_type('application/pdf');
   http_send_content_disposition('test.pdf');
   http_send_file('test.pdf');
?&gt;</div>
</pre>
<p>Como veis, únicamente establecemos la velocidad, las cabeceras para que el navegador sepa cómo manejar la petición, y finalmente mandamos un fichero de prueba llamado test.pdf que se encuentra en el directorio de trabajo actual.</p>
<p>El único problema está en la disponibilidad de la extensión HTTP. No creo que muchos servicios de alojamiento la tengan activada, aunque siempre se les puede pedir que lo instalen. Si quieres saber cómo hacerlo, simplemente tienes que hacer lo siguiente (en sistemas debian):</p>
<pre>$ sudo pecl install http_pecl</pre>
<p>Si te devolviera un código de error, quizás sea porque no tienes instaladas las herramientas de desarrollo de PHP, o alguna de las bibliotecas necesarias para compilar esta extensión. Tendrás que hacer lo siguiente:</p>
<pre>$ sudo aptitude install php5-dev
$ sudo aptitude install libcurl3-openssl-dev</pre>
<p>Ahora ya podrás compilarla. Sólo queda activarla en tu fichero php.ini. Añade esta línea:</p>
<pre>extension=http.so</pre>
<p>Y reinicia Apache con</p>
<pre>$ sudo /etc/init.d/apache2 restart</pre>
<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%2F28%2Flimitar-la-velocidad-de-descarga-en-php%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fchusete.es%2F2010%2F09%2F28%2Flimitar-la-velocidad-de-descarga-en-php%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/28/limitar-la-velocidad-de-descarga-en-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>10 cosas que quizás no sabías de PHP en la shell</title>
		<link>http://chusete.es/2010/09/24/10-cosas-que-quizas-no-sabias-de-php-en-la-shell/</link>
		<comments>http://chusete.es/2010/09/24/10-cosas-que-quizas-no-sabias-de-php-en-la-shell/#comments</comments>
		<pubDate>Fri, 24 Sep 2010 17:45:12 +0000</pubDate>
		<dc:creator>chusete</dc:creator>
				<category><![CDATA[desarrollo]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[cli]]></category>
		<category><![CDATA[consola]]></category>
		<category><![CDATA[shell]]></category>

		<guid isPermaLink="false">http://chusete.es/?p=856</guid>
		<description><![CDATA[Todos sabemos lo fantástico que es PHP como lenguaje de programación de páginas web. Lo que no muchos saben es que es igualmente fantástico como lenguaje para realizar programas multiplataforma para la shell. No todo es bash, Python, perl o Microsoft Powershell. Vamos a ver algunas de las cosas que quizás no sabías que podemos [...]]]></description>
			<content:encoded><![CDATA[<p>Todos sabemos lo fantástico que es PHP como lenguaje de programación de páginas web. Lo que no muchos saben es que es igualmente fantástico como lenguaje para realizar programas multiplataforma para la shell. No todo es bash, Python, perl o Microsoft Powershell. Vamos a ver algunas de las cosas que quizás no sabías que podemos hacer con PHP en la consola.</p>
<p><strong>Nota</strong>: Toda esta información está disponible en el <a href="http://www.php.net/manual/es/features.commandline.php">manual de documentación de PHP</a>.</p>
<h2>1. Ejecutar un script</h2>
<p>Podemos crearnos nuestros propios programas simplemente creando un fichero .php y ejecutándolo con el binario CLI php. Por ejemplo:</p>
<pre>&lt;?php
   echo "hola mundo!\n";
?&gt;</pre>
<p>Y ahora para ejecutarlo sólo tendríamos que llamar al binario php (php.exe en Windows) seguido del nombre del script. Supongamos que el ejemplo de arriba lo guardamos en un fichero que se llama test.php. Sería así:</p>
<pre>$ php test.php</pre>
<p>Y en sistemas Windows:</p>
<pre>&gt; php.exe test.php</pre>
<p>De esta forma, los dos mostrarían en pantalla el texto &#8220;hola mundo!&#8221;. Fácil, verdad? <img src='http://chusete.es/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h2>2. Hacer que el script se sea ejecutable</h2>
<p>En Windows tendremos que asociar la extensión .php al binario php.exe. De esa forma, al hacer doble clic sobre un fichero, este se ejecutará. Sin embargo, si quisiéramos que se pudiera ejecutar desde la consola, tendríamos que crear un fichero por lotes .bat que realice la llamada.</p>
<pre>@echo OFF
"C:\php\php.exe" test.php</pre>
<p>En sistemas Unix es más sencillo. Tenemos que añadir en la primera línea la ruta al binario que ejecuta el script, y posteriormente otorgamos permisos de ejecución al fichero. Y ya está, ya es ejecutable desde la consola y desde el entorno gráfico. El fichero quedaría así:</p>
<pre>#!/usr/bin/php
&lt;?php
   echo "hola mundo!\n";
?&gt;</pre>
<p>Y después damos permisos de ejecución, y ya podremos ejecutarlo:</p>
<pre>$ chmod +x test.php
$ ./test.php</pre>
<h2>3. Pasar parámetros al programa</h2>
<p>Supongamos un comando cualquier de la consola, por ejemplo &#8220;ls&#8221;. Este comando acepta numerosos parámetros para controlar su comportamiento. En PHP también podemos pasar parámetros. Sólo tenemos que tener en cuenta una cosa: Si el script no tiene permisos de ejecución, hay que pasar los parámetros tras los caracteres &#8220;&#8211;&#8221;. Es así para prevenir que el binario php los considere parámetros suyos. Veamos un ejemplo de cómo hacerlo:</p>
<p>$ php test.php &#8212; parametro1 parametro2<br />
$ ./test.php parametro1 parametro2</p>
<p>En el primer ejemplo ejecutamos el binario php y le pasamos como parámetro el nombre del script, por lo que en este caso añadimos los caracteres &#8220;&#8211;&#8221;. En cambio, en el segundo no es necesario, ya que el script tiene permisos de ejecución.</p>
<p>En sistemas Windows, como vimos arriba, habría que crear un fichero por lotes .bat, que para que pasara los parámetros a nuestro script quedaría así:</p>
<pre>@echo OFF
"C:\php\php.exe" test.php %*</pre>
<p>Bien, ya sabemos cómo enviar parámetros al script. Sólo nos queda saber cómo manejarlos. Pues muy sencillo. Hay dos variables globales para manejarlos:</p>
<ol>
<li>$argc &#8211; Contiene el número de parámetros que recibe el script</li>
<li>$argv &#8211; Es un array con los parámetros en sí</li>
</ol>
<h2>4. Usar PHP en como consola interactiva</h2>
<p>Al igual que ocurre con Python, PHP también puede ejecutarse en modo interactivo. Esto es, introducimos a mano los comandos en una &#8220;consola PHP&#8221;, y ésta los ejecuta al vuelo. Sólo hay que poner el parámetro &#8220;-a&#8221;. Por ejemplo:</p>
<pre>$ php -a
Interactive shell

php &gt; echo 5+8;
13
php &gt; function sumarDos($n)
php &gt; {
php { return $n + 2;
php { }
php &gt; var_dump(sumarDos(2));
int(4)
php &gt;</pre>
<p>Además, <strong>pulsando el botón tabulador</strong>, tendrás autocompletado de variables, funciones, clases, constantes, método estáticos y constantes de clases.</p>
<h2>5. Ejecutar una línea de código PHP al momento</h2>
<p>Podemos ejecutar el código que queramos usando el modificador &#8220;-r&#8221;. Imaginemos que queremos aplicar un hash md5 a un fichero de texto, y no tenemos en nuestro sistema el comando md5sum. Podríamos hacer lo siguiente:</p>
<pre>php -r 'echo md5(file_get_contents("fichero.txt"));'</pre>
<p>Lo que hacemos es ejecutar los comandos que hay entre las comillas simples:</p>
<ol>
<li>Cargamos el contenido de &#8216;fichero.txt&#8217;.</li>
<li>Le aplicamos el hash md5.</li>
<li>Lo mostramos en pantalla.</li>
</ol>
<p>¡Qué de cosas se pueden hacer con esto!</p>
<h2>6. Pasar contenidos a PHP por tuberías</h2>
<p>Muchas veces vemos comandos como:</p>
<pre>echo "hola mundo" | wc -c</pre>
<p>En este sencillo ejemplo lo que hemos hecho es en la salida estándar el texto &#8220;hola mundo&#8221;, que a su vez se envía a la entrada estándar del comando &#8220;wc -c&#8221;, que se encarga de contar el número de caracteres. ¿Cómo hacemos esto en PHP? Consultando la entrada estándar. En la versión CLI de PHP ponen a nuestra disposición 3 útiles constantes:</p>
<ol>
<li>STDIN &#8211; Stream a la entrada estándar.</li>
<li>STDOUT &#8211; Stream a la salida estándar.</li>
<li>STDERR &#8211; Stream a la salida de errores.</li>
</ol>
<p>Si quisiéramos contar el número de caracteres del texto recibido por la entrada estándar en PHP, podríamos hacer lo siguiente:</p>
<pre>echo "hola mundo" | php -r 'echo strlen(fgets(STDIN));'</pre>
<h2>7. Mostrar un fichero PHP sin comentarios ni espacios</h2>
<p>¿Nunca te has preguntado cuántos caracteres útiles tiene un gran proyecto? Con el modificador &#8220;-w&#8221; puedes verlo, pues eliminará todos los caracteres en blanco innecesarios (incluidos tabulares, retornos de carro, cambios de línea, etc), y todos los comentarios. Además, también podrás así minimizar el tamaño de los ficheros. Por ejemplo:</p>
<pre>$ php -w fichero.php</pre>
<h2>8. Consultar documentación desde la consola</h2>
<p>Supón que deseas conocer los parámetros de una función, o los métodos de una clase&#8230; Puedes consultarlo desde la consola, siempre y cuando tu versión de PHP esté compilada con la extensión <a href="http://www.php.net/manual/es/book.reflection.php">Reflection</a>. Esta familia de modificadores nos da 4 opciones:</p>
<ol>
<li>&#8220;&#8211;rf&#8221; &#8211; Muestra información de una función o de un método de una clase.</li>
<li>&#8220;&#8211;rc&#8221; &#8211; Muestra información de una clase (sus métodos, atributos, constantes&#8230;).</li>
<li>&#8220;&#8211;re&#8221; &#8211; Muestra información de una extensión (directivas .ini, funciones, constantes, clases, etc).</li>
<li>&#8220;&#8211;ri&#8221; &#8211; Muestra información sobre la configuración de una extensión. Esto es, lo mismo que devuelve phpinfo() para cada extensión. Si queremos ver la información general, usaremos &#8220;main&#8221; como nombre de extensión.</li>
</ol>
<p>Veamos un ejemplo en el que consultamos información de la función md5():</p>
<pre>$ php --rf md5
Function [ &lt;internal:standard&gt; function md5 ] {
  - Parameters [2] {
    Parameter #0 [ &lt;required&gt; $str ]
    Parameter #1 [ &lt;optional&gt; $raw_output ]
  }
}</pre>
<p>Una opción estupenda cuando no tenemos acceso a internet, ni nos hemos descargado la documentación de PHP a nuestro equipo.</p>
<h2>9. Decorar la sintaxis de nuestro código</h2>
<p>PHP nos ofrece una forma sencillísima de generar una versión HTML de nuestro código, coloreando y destacando cada parte. Sólo tendremos que ejecutarlo con el modificador &#8220;-w&#8221;. Una vez hecho esto, podremos exportarla al formato que queramos (PDF, Word, XHTML, etc). Muy útil cuando queremos imprimir un código fuente.</p>
<pre>$ php -w fichero.php</pre>
<p>Además, al estar disponible desde el propio binario de php, es muy fácil generar una versión HTML coloreada de cada fichero.</p>
<h2>10. La joya de la corona: definir código inicial, final, y para cada línea</h2>
<p>Si no tenías suficiente con sed o awk, ahora con PHP vas a poder hacer maravillas. Tenemos estos cuatro modificadores:</p>
<ol>
<li>&#8220;-B&#8221; &#8211; Código PHP a ejecutar antes que todo lo demás.</li>
<li>&#8220;-F&#8221; &#8211; Código PHP a ejecutar cuando finalice todo lo demás.</li>
<li>&#8220;-R&#8221; &#8211; Código PHP a ejecutar por cada línea. Tendremos $argn con la línea que se está procesando, y $argi con el número de línea.</li>
<li>&#8220;-F&#8221; &#8211; Fichero con el código PHP a ejecutar por cada línea.</li>
</ol>
<p>Veamos un ejemplo muy didáctico y muy poco útil de la documentación de PHP. Supongamos que queremos contar el número de líneas de un proyecto. Accedemos a su directorio y ejecutamos lo siguiente:</p>
<pre>$ find . | php -B '$lineas=0;' -R '$lineas += count(@file($argn));' -E 'echo "Total de líneas: $lineas\n";'</pre>
<p>Veámoslo paso a paso:</p>
<ol>
<li>En primer lugar ejecutamos el comando &#8220;find&#8221; de la consola de Linux. Nos mostrará (recursivamente) todos los ficheros del directorio actual.</li>
<li>El resultado se lo pasamos por la entrada estándar al binario php, el cual realiza lo siguiente:
<ol>
<li>En el modificador &#8220;-B&#8221; especificamos el código inicial. Simplemente inicializamos la variable $lineas a cero.</li>
<li>En el modificador &#8220;-R&#8221; decimos lo que se hará por cada línea recibida por la entrada estándar. En este caso, cada línea se corresponde con la ruta a un fichero:
<ol>
<li>Como vimos arriba, $argn contiene el texto que se está procesando. Contiene la ruta a un fichero</li>
<li>Pasamos esa ruta a la función file(), que genera un array donde cada índice contiene una fila del fichero leído.</li>
<li>Consultamos el tamaño del array, es decir, el número de líneas del fichero.</li>
<li>Incrementamos la variable $lineas con el valor obtenido en el paso anterior.</li>
</ol>
</li>
<li>Finalmente, el modificador &#8216;-E&#8217; se ejecuta al finalizar todo lo demás, y nos muestra como resultado el número total de líneas de texto que hay en todos los ficheros de la carpeta actual.</li>
</ol>
</li>
</ol>
<p>Sencillísimo y muy potente. Lo que más complicado puede resultar es recordar los 3 modificadores (B,F,R) y las dos variables ($argn y $argi).
<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%2F24%2F10-cosas-que-quizas-no-sabias-de-php-en-la-shell%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fchusete.es%2F2010%2F09%2F24%2F10-cosas-que-quizas-no-sabias-de-php-en-la-shell%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/24/10-cosas-que-quizas-no-sabias-de-php-en-la-shell/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Traducción de la documentación de PHP a Español</title>
		<link>http://chusete.es/2010/09/17/traduccion-de-la-documentacion-de-php-a-espanol/</link>
		<comments>http://chusete.es/2010/09/17/traduccion-de-la-documentacion-de-php-a-espanol/#comments</comments>
		<pubDate>Fri, 17 Sep 2010 00:53:36 +0000</pubDate>
		<dc:creator>chusete</dc:creator>
				<category><![CDATA[php]]></category>
		<category><![CDATA[documentación]]></category>
		<category><![CDATA[traducción]]></category>

		<guid isPermaLink="false">http://chusete.es/?p=854</guid>
		<description><![CDATA[Hace (mucho) tiempo que vengo pensando en colaborar en algún proyecto de software libre. Al fin y al cabo, hace años que casi todo el software que utilizo es libre. Gran parte del resultado es gracias al trabajo desinteresado de mucha gente por todo el mundo. Pensando en qué puedo y qué me apetece aportar, [...]]]></description>
			<content:encoded><![CDATA[<p>Hace (mucho) tiempo que vengo pensando en colaborar en algún proyecto de software libre. Al fin y al cabo, hace años que casi todo el software que utilizo es libre. Gran parte del resultado es gracias al trabajo desinteresado de mucha gente por todo el mundo.</p>
<p>Pensando en qué puedo y qué me apetece aportar, llegué a la conclusión de que el proyecto adecuado era PHP. No en vano es el proyecto de software libre que me da de comer <img src='http://chusete.es/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Si Apache no existiera podría utilizar <a href="http://www.lighttpd.net/">lighttpd</a>. Si Linux no existiera me instalaría algún <a href="http://en.wikipedia.org/wiki/Comparison_of_BSD_operating_systems">BSD</a>. Si MySQL tampoco existiera, mi gestor de bases de datos probablemente sería <a href="http://www.postgresql.org/">postgresql</a>. Sin Joomla! utilizaría <a href="http://drupal.org/">Drupal</a>. Sin Zend Framework usaría <a href="http://codeigniter.com/">Codeigniter</a>.</p>
<p>Y sin PHP&#8230; ¿¡qué haría yo sin PHP!? ¿Usar Python? Sí, pero <em>noslomismo</em>&#8230; <img src='http://chusete.es/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  A PHP le tengo un cariño especial. Mi primera página web la hice ya en PHP, en el año 2003, y desde entonces no he parado de aprender.</p>
<p>Bien, el proyecto ya está elegido. Ahora, ¿qué puedo hacer yo por PHP? Ya quisiera yo tener nivel para poder aportar algo al core de PHP. Hoy por hoy donde creo que puedo ser más útil es traduciendo la documentación a español. De modo que me puse en contacto con Yago (yago[arroba]php.net), quien amablemente me indicó los pasos a seguir para formar parte del equipo de traducción.</p>
<p>Tras un breve <em>training</em>, consistente en traducir un par de documentos y emplear la herramienta oficial de traducción, ya estoy dentro. ¡Y muy ilusionado!</p>
<p>Por ahora ya he detectado unas cuantas ventajas:</p>
<ul>
<li>Es agradecido ver que tu trabajo puede ayudar a otras personas.</li>
<li>Devuelves parte del favor que otros te han hecho al usar software libre.</li>
<li>Aprendes a trabajar en proyectos libres.</li>
<li>Puedes fardar de tener una cuenta @php.net (chuso[arroba]php.net).</li>
<li>En muchas empresas valoran que participes en proyectos libres.</li>
<li>Y lo más importante en mi opinión: Es una forma sensacional de no parar de aprender nuevas cosas de PHP.</li>
</ul>
<p>¿Alguien más se anima? Actualmente la documentación española es la tercera más traducida, lejos de la japonesa y la francesa. ¡Toda ayuda será bienvenida!
<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%2F17%2Ftraduccion-de-la-documentacion-de-php-a-espanol%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fchusete.es%2F2010%2F09%2F17%2Ftraduccion-de-la-documentacion-de-php-a-espanol%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/17/traduccion-de-la-documentacion-de-php-a-espanol/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Variables en PHP &#8211; zval</title>
		<link>http://chusete.es/2010/09/01/variables-en-php-zval/</link>
		<comments>http://chusete.es/2010/09/01/variables-en-php-zval/#comments</comments>
		<pubDate>Wed, 01 Sep 2010 05:07:36 +0000</pubDate>
		<dc:creator>chusete</dc:creator>
				<category><![CDATA[desarrollo]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[debug]]></category>
		<category><![CDATA[is_ref]]></category>
		<category><![CDATA[refcount]]></category>
		<category><![CDATA[tipos]]></category>
		<category><![CDATA[variables]]></category>
		<category><![CDATA[zval]]></category>

		<guid isPermaLink="false">http://chusete.es/?p=825</guid>
		<description><![CDATA[Todos los lenguajes de programación permiten almacenar valores en memoria. Estos valores generalmente pueden ser de varios tipos -numéricos, caracteres, booleanos, etc. Muchos lenguajes son de tipado estático, es decir, cuando se inicializa una variable, se declara también el tipo de dato que se va a alojar en ella; es el caso de lenguajes como [...]]]></description>
			<content:encoded><![CDATA[<p>Todos los lenguajes de programación permiten almacenar valores en memoria. Estos valores generalmente pueden ser de varios tipos -numéricos, caracteres, booleanos, etc. Muchos lenguajes son de <a href="http://en.wikipedia.org/wiki/Type_system#Static_typing">tipado estático</a>, es decir, cuando se inicializa una variable, se declara también el tipo de dato que se va a alojar en ella; es el caso de lenguajes como C o Java. Por contra, tenemos también el <a href="http://en.wikipedia.org/wiki/Type_system#Dynamic_typing">tipado dinámico</a>, donde se decide en tiempo de ejecución qué clase de dato contendrá la variable; es el caso de PHP o JavaScript.</p>
<h2>Tipos de datos en PHP</h2>
<p>PHP en concreto soporta los siguientes <a href="http://www.php.net/manual/en/language.types.intro.php">tipos</a>:</p>
<ul>
<li>Escalares
<ul>
<li>booleano</li>
<li>integer</li>
<li>float (o double).</li>
<li>string</li>
</ul>
</li>
<li>Compuestos
<ul>
<li>Array</li>
<li>Object</li>
</ul>
</li>
<li>Especiales
<ul>
<li>resource</li>
<li>NULL</li>
</ul>
</li>
</ul>
<p>Si en un momento dado quisiéramos mostrar el tipo de una variable, podemos utilizar la función gettype(). Por ejemplo:</p>
<pre name="code" class="php">&lt;?php
   $a = 'hola';
   $b = 42;
   $c = true;

   echo gettype($a); // Devuelve: string
   echo gettype($b); // Devuelve: integer
   echo gettype($c); // Devuelve: boolean
?&gt;</pre>
<p>Para comprobar si una variable es de un tipo determinado usaríamos <em>is_type(),</em> por ejemplo, <code>is_integer($a)</code>.</p>
<p>Por otra parte, si lo que quisiéramos es mostrar tanto el tipo como el valor de una variable, utilizaríamos la función <code>var_dump()</code>.</p>
<p>Además, al ser PHP un lenguaje de tipado dinámico, podemos forzar en tiempo de ejecución la conversión de un tipo a otro, técnica conocida como <a href="http://en.wikipedia.org/wiki/Type_conversion">casting</a>. Para ello podemos utilizar dos métodos: (1) O bien utilizado un <a href="http://www.php.net/manual/en/language.types.type-juggling.php#language.types.typecasting">cast</a>, (2) o bien mediante la función <code>settype()</code>.</p>
<p>A todo esto, hay que sumarle que PHP también puede cambiar el tipo de una variable en tiempo de ejecución dependiendo de su contexto. Por ejemplo, si a un string le sumamos un entero, PHP convertirá al string en entero en tiempo de ejecución. Esto puede desencadenar en <a href="http://www.php.net/manual/en/language.types.string.php#language.types.string.conversion">comportamientos inesperados</a>.</p>
<p>Como nota curiosa&#8230; Hace poco, en una entrevista de trabajo, me hicieron una pregunta. Si mal no recuerdo era algo tal que así: Si tenemos una variable a la que le asignamos la cadena &#8220;abc123&#8243;, y la comparamos con el operador == con el entero 0, ¿qué devuelve? La respuesta, aunque sorprendente, es que el resultado es true. Esto se debe a que PHP detecta que en este contexto la cadena debe comportarse como un entero, por lo que convierte &#8220;abc123&#8243; en un número: 0. ¿Es 0 igual a 0? Sí, por tanto el resultado el true.</p>
<h2>zval</h2>
<p>Pero volvamos a las variables. ¿Cómo se almacenan internamente? Cada una de ellas se almacena en un contenedor llamado &#8216;zval&#8217;. Un contenedor zval tiene:</p>
<ol>
<li><strong>Tipo de la variable</strong>. Como hemos visto, PHP tiene 8 tipos primitivos de datos.</li>
<li><strong>Valor de la variable</strong>. Esto es, el valor que le hemos asignado.</li>
<li><strong>refcount</strong>. Campo numérico que lleva la cuenta del número de variables que utilizan este contenedor.</li>
<li><strong>is_ref</strong>. Se trata de un booleano que indica si la variable está accedida por referencia.</li>
</ol>
<p>Los dos primeros campos están bastante claros, de modo que centrémonos en los dos últimos.</p>
<h2>refcount</h2>
<p>Hemos visto que el campo refcount lleva la cuenta de las variables que utilizan un determinado zval. Veámoslo con un ejemplo.</p>
<pre name="code" class="php">&lt;?php
   $a = "test";
   xdebug_debug_zval($a);
   // a: (refcount=1, is_ref=0)='test'
?&gt;</pre>
<p><strong>Nota: </strong>Para poder consultar el zval de una variable, tan sólo debemos llamar a la función <code>xdebug_debug_zval()</code> de la extensión <a href="http://www.xdebug.org/">Xdebug para PHP</a>.</p>
<p>Vemos que el campo refcount está a 1, es decir, sólo hay una variable que utilice este contenedor.</p>
<p>Veamos un ejemplo más avanzado:</p>
<pre name="code" class="php">&lt;?php
   $a = 'test';
   $b = $a;
   xdebug_debug_zval( 'a' );
   // a: (refcount=2, is_ref=0)='test'

   $b += 'ing';
   xdebug_debug_zval( 'a' );
   // a: (refcount=1, is_ref=0)='test'
?&gt;</pre>
<p>¿Qué ha pasado ahora? Vayamos paso a paso. En un primer lugar, creamos la variable $a a la que asignamos el valor &#8216;test&#8217;. Posteriormente creamos otra variable, $b, a la que le <strong>copiamos</strong> el mismo contenido que tiene $a. Al mostrar el zval de $a vemos que el valor refcount tiene ahora un 2. Esto es porque este contenedor zval está siendo utilizado por dos variables: $a y $b. Nótese que anteriormente he resaltado el verbo copiar, pues $b es una variable distinta a $a. Pero si son dos variables distintas, ¿por qué utilizan el mismo contenedor? Porque PHP es muy inteligente <img src='http://chusete.es/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Al tener las dos variables el mismo valor, hace que utilicen el mismo contenedor para ahorrar espacio en memoria. ¿Pero qué ocurre si modificamos ahora una de ellas? En el siguiente paso vemos cómo modificamos $b, añadiéndole el sufijo &#8216;ing&#8217;. PHP, que como digo es muy inteligente, ve que ya no tienen el mismo valor $a y $b, por lo que, ahora sí, crea un nuevo espacio en memoria para $b. Por esa razón si ahora vemos el zval de $a comprobaremos que su refcount está a 1.</p>
<p>Este valor es muy útil para la gestión de memoria de PHP. Este lenguaje, a diferencia de otros, contiene un <a href="http://en.wikipedia.org/wiki/Garbage_collection_(computer_science)">recolector de basura</a>, un proceso que se encarga de liberar la memoria de las variables y objetos que no se van a volver a usar. De este modo, el propio lenguaje se encarga por nosotros de limpiar la memoria. Por supuesto, el recolector de basura liberará todos los contenedores zval cuyo refcount esté a 0, pues significa que no están siendo utilizados por ninguna variable.</p>
<p>En cualquier momento podemos, además, forzar la eliminación de una variable, llamando a la función unset(). Ésta lo que hace es decrementar el valo refcount. Y como hemos visto, si llega a 0, se eliminará por completo el zval correspondiente.</p>
<h2>is_ref</h2>
<p>Si alguna vez has programado en C, sabrás bien lo que son los punteros: Se trata de variables cuyo valor es una dirección de memoria física, de modo que únicamente apuntan al lugar donde se encuentra su valor. Esto es muy útil para, por ejemplo, hacer que varias variables sean en realidad la misma. O para pasar a una función una variable, y que la función pueda modificar el valor de ésta. Esto es posible en PHP utilizando <a href="http://php.net/manual/en/language.references.php">referencias</a>.</p>
<p><strong>Nota</strong>: A partir de PHP5 cada vez que pasas un objeto a una función o método, éste se pasa siempre por referencia. Es decir, las modificaciones que se hagan de un objeto dentro de una función persistirán fuera de ésta.</p>
<p>Veamos dos ejemplos para comprender que son las variables por referencia:</p>
<pre name="code" class="php">&lt;?php
   $a = 'hello';
   $b = $a;
   echo $b; // Muestra 'test';
   $b = 'ciao';
   echo $a; // Muestra 'test';
   echo $b; // Muestra 'ciao';
?&gt;</pre>
<p>Simplemente copiamos a $b el valor de $a. Posteriormente modificamos $b, y comprobamos cómo sólo ha cambiado éste, pero no $a. El siguiente ejemplo es prácticamente igual, salvo que en lugar de copiar $a a $b, copiamos por referencia:</p>
<pre name="code" class="php">&lt;?php
   $a = 'hello';
   $b =&amp; $a;
   echo $b; // Muestra 'test';
   $b = 'ciao';
   echo $a; // Muestra 'ciao';
   echo $b; // Muestra 'ciao';
?&gt;</pre>
<p>En este caso, al haber usado el operador =&amp;, hemos hecho que <strong>$b sea en realidad la misma variable que $a</strong>. Y aquí es donde volvemos con zval. ¿Qué contiene ahora? Comprobémoslo:</p>
<pre>a: (refcount=2, is_ref=1)='ciao'</pre>
<p>¡Y ahí lo tenemos! Ahora el campo is_ref tiene valor true (1). Esto es porque, como hemos visto, este zval está siendo también apuntado por una variable por referencia. Además podemos comprobar cómo el refcount se ha incrementado a 2.</p>
<h2>zval en tipos compuestos</h2>
<p>Hasta ahora hemos visto ejemplos de zval en variables escalares. Vamos a ver un ejemplo de qué se almacena cuando es un tipo compuesto, como por ejemplo un array:</p>
<pre name="code" class="php">&lt;?php
   $a = array('foo' =&gt; 'bar', 'gen' =&gt; 'oma');
   xdebug_debug_zval('a');
?&gt;</pre>
<p>Y esto es lo que obtenemos:</p>
<p>a: (refcount=1, is_ref=0)=array (<br />
&#8216;foo&#8217; =&gt; (refcount=1, is_ref=0)=&#8217;bar&#8217;,<br />
&#8216;gen&#8217; =&gt; (refcount=1, is_ref=0)=&#8217;oma&#8217;<br />
)</p>
<p>¡Curioso! Un array lo que hace es crear una nueva tabla, distinta de la global, de valores zval. Pero la cosa se puede complicar bastante. Para terminar, vamos a ver el siguiente ejemplo extraído de la documentación de PHP:</p>
<pre name="code" class="php">&lt;?php
   $a = array( 'one' );
   $a[] =&amp; $a;
   xdebug_debug_zval( 'a' );
?&gt;</pre>
<p>Creamos un array con un solo elemento. Posteriormente creamos un segundo campo en el que asignamos una referencia circular al propio array. Obtenemos el siguiente resultado:</p>
<pre name="code" class="php">a: (refcount=2, is_ref=1)=array (
   0 =&gt; (refcount=1, is_ref=0)='one',
   1 =&gt; (refcount=2, is_ref=1)=...
)</pre>
<p>Supongamos que ahora hacemos una llamada a unset($a). El resultado esperado sería que se eliminara por completo de memoria el zval anterior. ¿Pero es esto lo que realmente ocurre? Como explicamos anteriormente, mediante unset() lo que hacemos es decrementar el refcount. Pero en este caso, tras llamar a unset() quedaría el siguiente zval huérfano sin ser eliminado de memoria pues su refcount vale 1:</p>
<pre name="code" class="php">(refcount=1, is_ref=1)=array (
   0 =&gt; (refcount=1, is_ref=0)='one',
   1 =&gt; (refcount=1, is_ref=1)=...
)</pre>
<p>No se elimina puesto que el item 1 del array sigue apuntando al propio array. Y al no haber ningún símbolo externo apuntando a este zval, no existe ningún mecanismo que nos permita liberar esta memoria, obteniendo un <a href="http://en.wikipedia.org/wiki/Memory_leak">memory leak</a>. Afortunadamente, desde PHP 5.3, esta memoria se libera automáticamente al finalizar la petición. Pero hasta entonces, sigue ocupando memoria, lo cual puede ser un problema en procesos de larga duración como por ejemplo un <a href="http://en.wikipedia.org/wiki/Daemon_(computer_software)">demonio</a>.</p>
<h2>Resumen</h2>
<p>En este artículo hemos pasado de lo más elemental, hasta conocer cómo se almacenan las variables internamente en PHP, y sus mecanismos de control. Conocemos los 8 típos primitivos de PHP, y cómo trabajar entre ellos. Sabemos qué es el campo refcount, lo que son los valores por referencia, el campo is_ref, y cómo afectan éstos al recolector de basuras. Del mismo modo, hemos visto cómo hay situaciones que pueden escapar a nuestro control, donde la memoria no queda libre a pesar de haber finalizado una variable.</p>
<p>Para más información podéis consultar:</p>
<ul>
<li><a href="http://www.php.net/manual/en/features.gc.refcounting-basics.php">Guía de PHP sobre el funcionamiento de refcount y cómo afecta al recolector de basuras</a> en php.net</li>
<li><a href="http://www.php.net/manual/en/features.gc.collecting-cycles.php">Información sobre el algoritmo de recolección de basuras de PHP</a> en php.net</li>
<li><a href="http://www.php.net/manual/en/features.gc.collecting-cycles.php"></a><a href="http://php.net/manual/en/language.types.php">Guía de los tipos soportados por PHP</a> en php.net</li>
<li><a href="http://porteightyeight.com/2008/03/18/the-truth-about-php-variables/">Otra guía introductoria a variables, referencias, y zval</a> en porteighveight.com</li>
<li><a href="http://php.net/manual/en/language.references.php">Valores por referencia</a> en php.net</li>
<li><a href="http://schlueters.de/blog/archives/141-References-and-foreach.html">Un curioso comportamiento inesperado en bucles foreach y referencias</a> en schlueters.de</li>
<li><a href="http://schlueters.de/blog/archives/125-Do-not-use-PHP-references.html">Interesante artículo sobre por qué no usar referencias en PHP</a> en schlueters.de</li>
</ul>
<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%2Fvariables-en-php-zval%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fchusete.es%2F2010%2F09%2F01%2Fvariables-en-php-zval%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/variables-en-php-zval/feed/</wfw:commentRss>
		<slash:comments>2</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>PHP 5.3.3 liberada</title>
		<link>http://chusete.es/2010/07/22/php-5-3-3-liberada/</link>
		<comments>http://chusete.es/2010/07/22/php-5-3-3-liberada/#comments</comments>
		<pubDate>Thu, 22 Jul 2010 21:13:31 +0000</pubDate>
		<dc:creator>chusete</dc:creator>
				<category><![CDATA[desarrollo]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://chusete.es/?p=775</guid>
		<description><![CDATA[Hace ya un año que PHP lanzó la versión 5.3.0, la última rama de desarrollo de la versión 5 que adelanta muchas de las funcionalidades más esperadas, como namespaces o closures. Hoy se ha liberado la versión 5.3.3. Se ha centrado sobre todo en mejorar el rendimiento y la seguridad de la rama 5.3, con [...]]]></description>
			<content:encoded><![CDATA[<p>Hace ya un año que <a href="http://www.php.net/archive/2009.php#id2009-06-30-1">PHP lanzó la versión 5.3.0</a>, la última rama de desarrollo de la versión 5 que adelanta muchas de las funcionalidades más esperadas, como namespaces o closures. Hoy <a href="http://www.php.net/archive/2010.php#id2010-07-22-2">se ha liberado la versión 5.3.3</a>. Se ha centrado sobre todo en mejorar el rendimiento y la seguridad de la rama 5.3, con más de 100 errores corregidos, por lo que se recomienda encarecidamente actualizar a la nueva versión.</p>
<p>Entre las novedades, se destacan:</p>
<ul>
<li>Actualizada la versión de sqlite a 3.6.23.1</li>
<li>Actualizada la versión de <a href="http://www.pcre.org/">PCRE</a> (Expresiones Regulares Compatibles con Perl) a la versión 8.02</li>
<li>Añadido FPM (Gestor de Procesos de FastCGI) SAPI. SAPI hace referencia a los módulos de PHP que hacen de interfaz al servidor web (<a href="http://en.wikipedia.org/wiki/Server_Application_Programming_Interface">Server Application Programming Interface</a>)</li>
<li>Añadido soporte para <a href="http://www.php.net/manual/en/stream.filters.php">stream filter</a> de la extensión mcrypt.</li>
</ul>
<p>¡A disfrutarlo!
<div class="tweetmeme_button" style="float: left; margin-right: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fchusete.es%2F2010%2F07%2F22%2Fphp-5-3-3-liberada%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fchusete.es%2F2010%2F07%2F22%2Fphp-5-3-3-liberada%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/07/22/php-5-3-3-liberada/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

