<?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>David Rojo González &#124; Tecnología, programación web, SEO</title>
	<atom:link href="http://blog.davidrojo.es/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.davidrojo.es</link>
	<description>Otro sitio realizado con WordPress</description>
	<lastBuildDate>Sun, 23 Oct 2011 19:11:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Detectar idioma del navegador con PHP</title>
		<link>http://blog.davidrojo.es/2011/10/detectar-idioma-del-navegador-con-php/</link>
		<comments>http://blog.davidrojo.es/2011/10/detectar-idioma-del-navegador-con-php/#comments</comments>
		<pubDate>Sun, 02 Oct 2011 11:10:12 +0000</pubDate>
		<dc:creator>David</dc:creator>
				<category><![CDATA[Programación]]></category>
		<category><![CDATA[codigos]]></category>
		<category><![CDATA[idiomas]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programacion]]></category>

		<guid isPermaLink="false">http://blog.davidrojo.es/?p=358</guid>
		<description><![CDATA[Cuando queremos hacer una web con varios idiomas, debemos tener en cuenta que deberiamos ofrecerle al usuario de forma predeterminada la web en el idioma que el tiene configurado el navegador. Muchas veces se confunde el pais de procedencia del usuario con su idioma, y debemos distinguirlo, puesto que puede que nuestro usuario nos visite <a href='http://blog.davidrojo.es/2011/10/detectar-idioma-del-navegador-con-php/'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>Cuando queremos hacer una web con <strong>varios idiomas</strong>, debemos tener en cuenta que deberiamos ofrecerle al usuario de forma predeterminada la web en el idioma que el tiene configurado el <strong>navegador</strong>. Muchas veces se confunde el pais de procedencia del usuario con su idioma, y debemos distinguirlo, puesto que puede que nuestro usuario nos visite desde francia pero su idioma sea el castellano.</p>
<p>Para ello detectaremos el idioma del usuario a partir del navegador. Por defecto el navegador nos envia los idiomas que acepta el usuario en una lista <strong>ordenada por prioridad</strong>. Este dato lo podemos encontrar en la super variable <strong>$_SERVER['HTTP_ACCEPT_LANGUAGE']</strong>. Esta variable tiene la siguiente forma:</p>
<pre class="brush: plain; title: ; notranslate">Accept-Language: ca,es-es;q=0.8,es;q=0.6,en-us;q=0.4,en;q=0.2</pre>
<p>Por cada idioma que acepta el usuario aparece separado por &#8220;,&#8221; y en cada idioma aparece una q de <strong>prioridad</strong>.</p>
<p>Para ofrecer al usuario la web en su idioma vamos a programar primero de todo, una funcion que nos procese este string y nos devuelva un array ordenado por prioridad de idioma.</p>
<pre class="brush: php; title: ; notranslate">
function getAcceptedLanguages(){
  preg_match_all('/([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $lang_parse);
  if (count($lang_parse[1])) {
    $langs = array_combine($lang_parse[1], $lang_parse[4]);
    foreach ($langs as $lang =&gt; $val) {
      if ($val === '')
        $rlangs[substr($lang, 0, 2)] = 1;
      else if ($rlangs[substr($lang, 0, 2)] &lt; $val)
        $rlangs[substr($lang, 0, 2)] = $val;
    }
    arsort($rlangs, SORT_NUMERIC);
  }
  else $rlangs = array(&quot;es&quot; =&gt; 1);
  return $rlangs;
}
</pre>
<p>Esta función, segun el string mostrado antes de <strong>HTTP_ACCEPT_LANGUAGE</strong>, nos devolveria un array como el siguiente:</p>
<pre class="brush: plain; title: ; notranslate">
Array (
  [ca] =&gt; 1
  [es] =&gt; 0.8
  [en] =&gt; 0.4
);
</pre>
<p>Cada posicion del array, contiene como clave el <strong>idioma</strong>, y como valor la <strong>prioridad </strong>del usuario. Ahora que ya tenemos este array, simplemente debemos compararlo con los idiomas en los que ofrecemos nuestra página y por defecto mostrarla en el idioma de mayor prioridad para el usuario:</p>
<pre class="brush: php; title: ; notranslate">
function autoDetectLanguage(){
  $langs = $this-&gt;getAcceptedLanguages();
  foreach ($langs as $lang =&gt; $val) {
    foreach($this-&gt;_pagelangs as $key =&gt; $l){
      if (strpos($lang, $key) === 0) {
        return $key;
      }
    }
  }
  return DEFAULT_LANGUAGE;
}
</pre>
<p>El valor de $this-&gt;_pagelangs es un array con los idiomas en los que está de la página dónde cada clave del array es el código del idioma. El valor de cada item del array puede ser cualquier cosa:</p>
<pre class="brush: php; title: ; notranslate"> $this-&gt;_pagelangs = array( &quot;es&quot; =&gt; &quot;Español&quot;, &quot;en&quot; =&gt; &quot;Inglés&quot; );</pre>
<p>La constante <strong>DEFAULT_LANGUAGE </strong>define el idioma por defecto de la página si no se encuentra concordancia con los idiomas del vistante.</p>
<p>La función <strong>autoDetectLanguage </strong>nos devolverá el idioma al que mostrar la página, y a partir de ahí podemos hacer una redirección a la url que se desee para configurar el idioma. Esta función solo debemos llamarla <strong>la primera vez</strong> que el usuario entra en la página y que aun no sepamos su idioma. Una vez lo sepamos ya no es necesario.</p>
<p>Cualquier duda o comentario es bien recibido.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.davidrojo.es/2011/10/detectar-idioma-del-navegador-con-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Caché en el navegador con imágenes generadas en PHP</title>
		<link>http://blog.davidrojo.es/2011/09/cache-en-el-navegador-con-imagenes-generadas-en-php/</link>
		<comments>http://blog.davidrojo.es/2011/09/cache-en-el-navegador-con-imagenes-generadas-en-php/#comments</comments>
		<pubDate>Sat, 24 Sep 2011 09:47:53 +0000</pubDate>
		<dc:creator>David</dc:creator>
				<category><![CDATA[Programación]]></category>
		<category><![CDATA[codigos]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programacion]]></category>

		<guid isPermaLink="false">http://blog.davidrojo.es/?p=343</guid>
		<description><![CDATA[Muchas veces nos olvidamos que un pequeño cambio puede cambiar drásticamente el rendimiento de una página. En este caso vamos a hablar un poco de la caché de los navegadores. El navegador cuando entra en una página, como norma general, se descarga todo su contenido, esto supone que la primera vez que se entra en <a href='http://blog.davidrojo.es/2011/09/cache-en-el-navegador-con-imagenes-generadas-en-php/'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>Muchas veces nos olvidamos que un pequeño cambio puede cambiar drásticamente el rendimiento de una página. En este caso vamos a hablar un poco de la <strong>caché de los navegadores</strong>.</p>
<p>El navegador cuando entra en una página, como norma general, se descarga <strong>todo su contenido</strong>, esto supone que la primera vez que se entra en una página se tenga que transferir mucha información. Imágenes, CSS, Javascripts, etc&#8230;</p>
<p>Los navegadores hace muchísimo tiempo que utlizan una <strong>caché interna</strong> para así acelerar el proceso de carga de las páginas. Ésto hace que si un navegador accede a una página y descarga el archivo styles.css por ejemplo, la próxima vez que cargue la página no lo descargará, a menos que el archivo haya cambiado. Esto, actualmente, se hace comprobando los <a href="http://en.wikipedia.org/wiki/HTTP_header"><strong>headers</strong> </a>que envia el servidor web del archivo. Si el archivo ha sido modificado, o su tiempo en caché ha expirado, se descarga de nuevo, sino se utiliza el archivo descargado previamente. Gracias a ésta técnica se cargan <strong>más rápido</strong> las páginas, ya que las imágenes y archivos complementarios solo se descargan una vez, y posteriormente se sirven de la caché local del navegador. Además es una tarea que incorpora automáticamente el servidor web y no debemos preocuparnos por ella.</p>
<p>Ahora bien, existe un pequeño problema con las <strong>páginas dinámicas</strong>. Éstas páginas se generan en el momento que el usuario acceden a ella, es decir, su fecha de creacion es justamente la fecha actual de la página, y es algo que debe ser así, ya que queremos que al usuario se le muestre el contenido más nuevo de la página, pero en situaciones queremos que no sea así. Podemos ver el caso de las imágenes generadas por PHP (como vimos en entradas anteriores).</p>
<p>Si generamos imágenes desde PHP, estas siempre seran <strong>generadas al momento</strong>, lo que provoa que, aunque la imagen sea la misma, el navegador no pueda hacer caché ya que las <strong>cabeceras </strong>del archivo le indican que la imágen se acaba de generar ahora. Por ello vamos a ver como generar las cabeceras necesarias para hacerle entender al navegador que la imágen es nueva. Básicamente seguiremos este diagrama:</p>
<p><a href="http://blog.davidrojo.es/wp-content/uploads/2011/09/Dibujo1.png"><img class="aligncenter size-full wp-image-345 colorbox-343" title="Diagrama de flujo caché" src="http://blog.davidrojo.es/wp-content/uploads/2011/09/Dibujo1.png" alt="Diagrama de flujo caché" width="464" height="294" /></a></p>
<p>Ante todo, debemos mostrar los headers para informarle al navegador que puede hacer caché de la imagen y que periodo de cache le damos:</p>
<pre class="brush: plain; title: ; notranslate">header(&quot;Cache-Control: private, max-age=10800, pre-check=10800&quot;);

header(&quot;Expires: &quot; . date(DATE_RFC822,strtotime(&quot; 2 day&quot;)));</pre>
<p>Después  necesitaremos saber si la imagen solicitada existe o no. Para ello simplemente con <strong><a href="http://php.net/manual/es/function.file-exists.php">file_exists</a></strong> obtendremos la respuesta</p>
<pre class="brush: php; title: ; notranslate">if (file_exists($imagen)){
    //TO DO...
}
else{
    header(&quot;Redirect: image-not-found.jpg&quot;);
}</pre>
<p>Ahora vamos a ver como comprobar si la imagen existe en la cache del navegador. Para ello vamos a ver como solicita una imagen el navegador cuando la tiene en caché.</p>
<p>Si el navegador no tiene la imagen en caché, simplemente hará una petición GET del archivo, pero si ya la tiene en la caché, hara una petición enviando la información en las cabeceras HTTP de la imagen que está pidiendo. Básicamente nos interesan las siguientes cabeceras:</p>
<pre class="brush: plain; title: ; notranslate">If-Modified-Since:Sun, 03 Apr 2011 16:50:39 GMT
If-None-Match:&quot;256c42e-580c-715cd5c0&quot;
ETag:&quot;256c42e-580c-715cd5c0&quot;</pre>
<p>Esto nos informa, de la fecha de creación de la imágen que está solicitando que tiene en caché, y de un codigo generado para dicha imágen.</p>
<p>Si nosotros queremos realizar las operaciones de caché en nuestro script, deberemos <strong>comprobar nosotros</strong> cuando la imagen es válida y cuando no. Por lo tanto tendremos que comprobar que la imagen que tenemos fue creada antes de la que tiene el navegador, y que el códdigo coincide. En ese caso le informaremos al navegador que la imagen es la misma, en caso contrario le <strong>deberemos proporcionar</strong> los nuevos datos y servirle la imágen.</p>
<p>Para generar nuestro código, simplemente cogeremos la fecha de modificación de la imágen y lo pasaremos por un <strong><a href="http://es2.php.net/manual/es/function.md5.php">md5</a></strong>. Para hacer esto lo hacemos de la siguiente manera:</p>
<pre class="brush: php; title: ; notranslate">
$fp = fopen($imagen, &quot;r&quot;);
$etag = md5(serialize(fstat($fp)));
fclose($fp);
</pre>
<p>Ahroa simplemente comprobamos que haya coincidencia en los parámetros y generamos las cabeceras necesarias:</p>
<pre class="brush: php; title: ; notranslate">
header('Etag: '.$etag);
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) &amp;&amp; (strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) &gt;= filemtime($imagen) || trim($_SERVER['HTTP_IF_NONE_MATCH']) == $etag) ) {
    header('Last-Modified: '.gmdate('D, d M Y H:i:s', filemtime($imagen)).' GMT', true, 304);
    exit();
}
else{
    header('Last-Modified: '.gmdate('D, d M Y H:i:s', filemtime($imagen)).' GMT');
    readfile($imagen);
}
</pre>
<p>Tal y como vemos en el código, comprobamos si estamos recibiendo el parámetro <strong>If-Modified-Since,</strong> y comprobamos que esta fecha sea mayor que la del archivo, luego comprobamos también que <strong>If-None-Match</strong> coincida con el archivo, si todo es correcto, enviamos el header <strong>Last-Moddified</strong>, con un código <strong>304</strong>, que significa que el contenido no ha cambiado, y salimos del script. Si no coincide, enviamos el <strong>Last-Modified</strong> igual pero sin codigo 304 para hacer que el navegador descargue el contenido, y leemos el servimos del fichero.</p>
<p>Por lo tanto el codigo final es el siguiente:</p>
<pre class="brush: php; title: ; notranslate">header(&quot;Cache-Control: private, max-age=10800, pre-check=10800&quot;);header(&quot;Expires: &quot; . date(DATE_RFC822,strtotime(&quot; 2 day&quot;)));
if (file_exists($imagen)){
$fp = fopen($imagen, &quot;r&quot;);
&lt;pre&gt;    $etag = md5(serialize(fstat($fp)));
    fclose($fp);
    header('Etag: '.$etag);
    if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) &amp;&amp; (strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) &gt;= filemtime($imagen) || trim($_SERVER['HTTP_IF_NONE_MATCH']) == $etag) ) {
        header('Last-Modified: '.gmdate('D, d M Y H:i:s', filemtime($imagen)).' GMT', true, 304);
        exit();
    }
    else{
        header('Last-Modified: '.gmdate('D, d M Y H:i:s', filemtime($imagen)).' GMT');
        readfile($imagen);
    }&lt;/pre&gt;
}
else{
 header(&quot;Location: image-not-found.jpg&quot;);
}</pre>
<p>Por supuesto podemos combinar todo esto con el escalado de imágenes y otras operaciones. Aprovechar la capacidad de la caché de los navegadores, sobre todo en contenidos que se estan sirviendo continuamente en nuestra página, nos hará reducir en gran medida el tiemo de carga de páginas y sobre todo, el ancho de banda de nuestro servidor. En un cliente con esta simple operación, se ha reducido el <strong>ancho de banda</strong> del servidor en un <strong>65%</strong>. Y con ello también se <strong>reduce </strong>el uso de <strong>CPU </strong>y de <strong>memoria</strong>.</p>
<p>Cualquier duda o comentario es bien recibido.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.davidrojo.es/2011/09/cache-en-el-navegador-con-imagenes-generadas-en-php/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Instalar Imagick en PHP con Ubuntu</title>
		<link>http://blog.davidrojo.es/2011/07/instalar-imagick-en-php-con-ubuntu/</link>
		<comments>http://blog.davidrojo.es/2011/07/instalar-imagick-en-php-con-ubuntu/#comments</comments>
		<pubDate>Wed, 27 Jul 2011 09:15:23 +0000</pubDate>
		<dc:creator>David</dc:creator>
				<category><![CDATA[Manuales]]></category>
		<category><![CDATA[imagick]]></category>
		<category><![CDATA[manuales]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://blog.davidrojo.es/?p=235</guid>
		<description><![CDATA[Bueno, hace unos días publique una entrada de como usar Imagick para generar thumbnails de otras imágenes y de pdfs, ahora (más vale tarde que nunca) os voy a mostrar como instalar Imagick en PHP sobre Ubuntu. Primero de todo instalaremos las librerias necesarias, tanto de php como de ImageMagick Ahora deberiamos hacer Si funciona <a href='http://blog.davidrojo.es/2011/07/instalar-imagick-en-php-con-ubuntu/'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>Bueno, hace unos días publique una entrada de como usar Imagick para generar thumbnails de otras imágenes y de pdfs, ahora (más vale tarde que nunca) os voy a mostrar como instalar Imagick en PHP sobre Ubuntu.</p>
<p>Primero de todo instalaremos las librerias necesarias, tanto de php como de ImageMagick</p>
<pre class="brush: plain; title: ; notranslate">sudo apt-get install php-pear php5-dev imagemagick libmagick9-dev php5-imagick</pre>
<p>Ahora deberiamos hacer</p>
<pre class="brush: plain; title: ; notranslate">pecl install imagick</pre>
<p>Si funciona perfecto, pero a mi me daba un error de que no encontraba el método raiseError, así que la otra opción es instalar el paquete manualemnte. Para ello descargar la última versión de la extensión Imagick de  <a href="http://pecl.php.net/package/imagick" target="_blank">http://pecl.php.net/package/imagick</a></p>
<p>Descomprimimos el archvo descargado y en la consola entramos en el directorio dónde se encuentran todos los archivos y hacemos</p>
<pre class="brush: plain; title: ; notranslate">
phpize
./configure
make
sudo make install
</pre>
<p>Si instalamos ghostcript tendremos acceso a las funciones de pdf de Imagick. Para ello simplemente tenemos que hacer</p>
<pre class="brush: plain; title: ; notranslate">sudo apt-get install ghostcript</pre>
<p>Espero que os sea de ayuda.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.davidrojo.es/2011/07/instalar-imagick-en-php-con-ubuntu/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Integrar botón +1 de Google</title>
		<link>http://blog.davidrojo.es/2011/06/integrar-boton-1-de-google/</link>
		<comments>http://blog.davidrojo.es/2011/06/integrar-boton-1-de-google/#comments</comments>
		<pubDate>Tue, 28 Jun 2011 16:29:04 +0000</pubDate>
		<dc:creator>David</dc:creator>
				<category><![CDATA[Programación]]></category>
		<category><![CDATA[google +1]]></category>
		<category><![CDATA[integrar]]></category>
		<category><![CDATA[programacion]]></category>

		<guid isPermaLink="false">http://blog.davidrojo.es/?p=330</guid>
		<description><![CDATA[Bueno, como muchos de vosotros sabéis, Google ha sacado el botón +1. Personalmente veo que es una estrategia que puede dar grandes resultados a Google, y sobre todo a la forma de buscar contenidos en la web, falta ver si la gente lo adopta correctamente. En resumen, és el típico &#8220;Me gusta&#8221; de facebook, pero <a href='http://blog.davidrojo.es/2011/06/integrar-boton-1-de-google/'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>Bueno, como muchos de vosotros sabéis, Google ha sacado el botón +1. Personalmente veo que es una estrategia que puede dar grandes resultados a Google, y sobre todo a la forma de buscar contenidos en la web, falta ver si la gente lo adopta correctamente.</p>
<p>En resumen, és el típico &#8220;Me gusta&#8221; de facebook, pero con utilidad, me explico&#8230; Actualmente el me gusta de facebook, para lo único que sirve es para compartir una página con tus amigos, hoy le das a &#8220;Me gusta&#8221; y mañana ese &#8220;Me gusta&#8221; ha caido en la time line y desaparece. Pero el +1 de Google va más allá. Utilizarán esta información para refinar las búsquedas en los resultados, permitiendo que si amigos tuyos han dado un +1 a una página, ésta gane posiciones cuando realices una  búsqueda.</p>
<p>La integración de dicho botón es de lo más sencillo que hay. Simplemente hay que introducir el código que encontraremos en <a href="http://www.google.com/intl/es/webmasters/+1/button/index.html">http://www.google.com/intl/es/webmasters/+1/button/index.html</a></p>
<p>Incluimos el javascript en el head</p>
<pre class="brush: xml; title: ; notranslate">&lt;script type=&quot;text/javascript&quot; src=&quot;https://apis.google.com/js/plusone.js&quot;&gt;&lt;/script&gt;</pre>
<p>y luego donde queramos introducir el +1 incluimos lo siguiente:</p>
<pre class="brush: plain; title: ; notranslate">&lt;g:plusone&gt;&lt;/g:plusone&gt;</pre>
<p>En la página que os he puesto antes, podeis configurar idioma y atamaño y os generará el código necesario.</p>
<p>Como recomendación, debereis tener los metas title y description correctos ya que son los que se usaran para compartir. También deberemos tener el canonical si la pagina que vamos a compartir tiene varias urls distintas (algo que ya deberiamos estar haciendo). Podéis encontrar más información aquí: <a href="http://googlewebmastercentral.blogspot.com/2009/02/specify-your-canonical.html">http://googlewebmastercentral.blogspot.com/2009/02/specify-your-canonical.html</a></p>
<p>Por último el meta image_src nos permitirá definir la imagen a compartir. Básicamente debemos añadir en nuestro head el siguiente código:</p>
<pre class="brush: xml; title: ; notranslate">&lt;link rel=&quot;image_src&quot; href=&quot;URL IMAGEN PRICNIPAL&quot; /&gt;</pre>
<p>Esto también nos servirá a la hora de compartir en Facebook una url.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.davidrojo.es/2011/06/integrar-boton-1-de-google/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Custom login en wordpress</title>
		<link>http://blog.davidrojo.es/2011/06/custom-login-en-wordpress/</link>
		<comments>http://blog.davidrojo.es/2011/06/custom-login-en-wordpress/#comments</comments>
		<pubDate>Tue, 21 Jun 2011 16:26:44 +0000</pubDate>
		<dc:creator>David</dc:creator>
				<category><![CDATA[Programación]]></category>
		<category><![CDATA[login]]></category>
		<category><![CDATA[manuales]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[wordpress]]></category>
		<category><![CDATA[wordpress plugins]]></category>

		<guid isPermaLink="false">http://blog.davidrojo.es/?p=301</guid>
		<description><![CDATA[La verdad es que estoy bastante enamorado de wordpress ultimamente, me gusta mucho la facilidad de actualizarse, cambiar de temas, customizarlos y la instalación de plugins que le dan una gran potencia a este sistema de blogs, pero también es verdad que a nivel empresarial, el hecho de tener un sistema de gestion de usuarios <a href='http://blog.davidrojo.es/2011/06/custom-login-en-wordpress/'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>La verdad es que estoy bastante enamorado de wordpress ultimamente, me gusta mucho la facilidad de actualizarse, cambiar de temas, customizarlos y la instalación de plugins que le dan una gran potencia a este sistema de blogs, pero también es verdad que a nivel empresarial, el hecho de tener un sistema de gestion de usuarios externo complica las cosas, sobre todo para los encargados de usar el blog.</p>
<p>No hay nada peor en una empresa que tener <strong>varios sistemas independientes</strong> entre ellos y ademas que los usuarios tengan que estar recordando usuarios y contraseñas en cada sistema, y que un cambio de contraseña en un sitio no afecte a los demás, y viceversa.</p>
<p>Por ello me puse a investigar y ví varias paginas dónde explicaban cómo autentificarnos en wordpress con el usuario y contraseña de otro servico.</p>
<p>Despues de varias pruebas y modificaciones, conseguí que funcionase, puesto que algunos códigos que encontré no eran compatibles o directamente no funcionaban correctamente (almenos no conseguía que funcionasen), decidí montarlo yo mismo a partir de lo que iva viendo. Como es la primera vez que me he puesto a tocar un plugin en wordpress, he ido bastante lento y seguramente que habrán maneras mejores de hacerlo, pero ahí va mi propuesta.</p>
<p>Este código esta basado en el plugin <a href="http://wordpress.org/extend/plugins/external-database-authentication/installation/">External DB authentication</a></p>
<p>La idea es muy sencilla, cuando un usuario se identifica en el panel de administración de wordpress, <strong>capturamos el login</strong>, y comprobamos en nuestro sistema si ese login es correcto y puede acceder al blog. Si es así <strong>actualizamos el usuario</strong> en wordpress con los datos del usuario en nuestro sistema, así cuando wordpress intente loguear al usuario se lo encontrará en la tabla con los datos correctos.</p>
<p>Para ello crearemos un fichero en la carpeta /wp-content/plugins. Podemos llamarlo &#8220;customAuthenticate.php&#8221;. Es básico que incluyamos la siguiente información al principio del archivo (almenos es lo que creo que se ha de hacer):</p>
<pre class="brush: php; title: ; notranslate">
/*
Plugin Name: Custom Authentication System
Plugin URI: http://blog.davidrojo.es/2011/06/custom-login-en-wordpress/
Description: This plugin allows to customize Login process with a personal system.
Version: 1.0
Author: David Rojo
Author URI: http://www.davidrojo.es
License: GPL2
*/
</pre>
<p>Lógicamente podeis poner aquí la información que queráis. Una vez creado este archivo, si vamos al menú de plugins de wordpress, nos aparecerá nuestro plugin para activarlo.</p>
<p>A continuación en nuestro fichero <strong>capturaremos </strong>el proceso de <strong>autentificación </strong>de wordpress:</p>
<pre class="brush: php; title: ; notranslate">
add_filter('wp_authenticate', 'customAuthentication', 1, 2 );

function customAuthentication( $username, $password) {

}
</pre>
<p>Y ahora tenemos simplemente que programar <strong>nuestro login</strong> dentro de la función <strong>customAuthentication</strong>. El resultado seria algo similar a lo siguiente:</p>
<pre class="brush: php; title: ; notranslate">
add_filter('wp_authenticate', 'customAuthentication', 1, 2 );

function customAuthentication( $username, $password) {
  $user = p_obtenerUsuario($username, $password);
  if ($user){
    // HEMOS ENCONTRADO EL USUARIO EN NUESTRO SISTEMA
    $userarray['user_login'] = $user[&quot;username&quot;];
    $userarray['user_pass'] = $password;
    $userarray['first_name'] = $user[&quot;nombre&quot;];
    $userarray['last_name'] = $user[&quot;apelildos&quot;];
    $userarray['user_email'] = $user[&quot;email&quot;];&lt;/pre&gt;
    // COMPROBAMOS SI EL USUARIO YA ESTÁ EN WORDPRESS
    if ($id = username_exists($username)) {
      // ACTUALIZAMOS EL USUARIO EN WORDPRESS
      $userarray['ID'] = $id;
      wp_update_user($userarray);
    }
    else{
      // INSERTAMOS EL USUARIO EN WORDPRESS
      wp_insert_user($userarray);&lt;/pre&gt;
    }
  }
  else{ // USUARIO INCORRECTO
    remove_action('authenticate', 'wp_authenticate_username_password', 20);
  }
}
</pre>
<p>Ahora solo nos queda programar la función <strong>p_obtenerUsuario</strong>, en la cual deberemos devolver NULL o false si el usuario no existe o su contraseña es incorrecta, en caso contrario deberemos devolver los datos del usuario como un <strong>array asociativo</strong>, con los datos necesarios para insertar el usuario en wordpress tal y como se ve en el paso anterior.</p>
<p>En nuestro caso vamos a conectar a una base de datos donde hay una tabla de usuarios con sus <strong>contraseñas en md5</strong> y una columna blog indica si el usuario puede acceder al blog, asumiermos que tambien tiene las columnas username, nombre, apellidos y email. Si estas columnas tuviesen otro nombre, o estuvieran en otra tabla, se deberia hacer un <strong>mapeo </strong>para devolverlo correctamente, o cambiar en el paso anterior los nombres de las claves del array asociativo $user.</p>
<pre class="brush: php; title: ; notranslate">
function p_obtenerUsuario($username, $password){
  $mydb = new wpdb(DB_USER, DB_PASS, DB_NAME, DB_HOST);
  $r = $mydb-&gt;get_row( $mydb-&gt;prepare( &quot;SELECT * FROM usuarios WHERE username = %s AND pass = %s AND blog = 1&quot;, $username, md5($password)), ARRAY_A);
  return $r;
}
</pre>
<p>Lógicamente se deba cambiar DB_USER, DB_PASS, DB_NAME y DB_HOST por las credenciales de la base de datos a donde vayamos a conectar.</p>
<p>Por último deberíamos desactivar todas las opciones de recordar contraseña, registro, etc, ya que ahora la gestion de usuarios se deberia hacer desde <strong>nuestro sistema alternativo</strong>. Para ello ñadiremos el siguiente código:</p>
<pre class="brush: php; title: ; notranslate">
//disables the (useless) password reset option in WP when this plugin is enabled.
function ext_db_show_password_fields() {
  return 0;
}

/* * Disable functions.  Idea taken from http auth plugin. */
function disable_function_register() {
  $errors = new WP_Error();
  $errors-&gt;add('registerdisabled', __('User registration is not available from this site, so you can\'t create an account or retrieve your password from here. See the message above.'));
  ?&gt;&lt;/form&gt;&lt;br /&gt;&lt;div id=&quot;login_error&quot;&gt;User registration is not available from this site, so you can't create an account or retrieve your password from here. See the message above.&lt;/div&gt;
  &lt;p id=&quot;backtoblog&quot;&gt;&lt;a href=&quot;&lt;?php bloginfo('url'); ?&gt;/&quot; title=&quot;&lt;?php _e('Are you lost?') ?&gt;&quot;&gt;&lt;?php printf(__('&amp;larr; Back to %s'), get_bloginfo('title', 'display' )); ?&gt;&lt;/a&gt;&lt;/p&gt;
  &lt;?php
  exit();
}
function disable_function() {
  $errors = new WP_Error();
  $errors-&gt;add('registerdisabled', __('User registration is not available from this site, so you can\'t create an account or retrieve your password from here. See the message above.'));
  login_header(__('Log In'), '', $errors);
  ?&gt;
  &lt;p id=&quot;backtoblog&quot;&gt;&lt;a href=&quot;&lt;?php bloginfo('url'); ?&gt;/&quot; title=&quot;&lt;?php _e('Are you lost?') ?&gt;&quot;&gt;&lt;?php printf(__('&amp;larr; Back to %s'), get_bloginfo('title', 'display' )); ?&gt;&lt;/a&gt;&lt;/p&gt;
  &lt;?php
  exit();
}
add_action('lost_password', 'disable_function');
add_action('user_register', 'disable_function');
add_action('register_form', 'disable_function_register');
add_action('retrieve_password', 'disable_function');
add_action('password_reset', 'disable_function');
add_filter('show_password_fields','ext_db_show_password_fields');
</pre>
<p>Con todo esto tendremos listo nuestro plugin, recordad activarlo en la seccion plugins del panel de administración de wordpress. Cualquier duda, comentario, mejora, etc, son bien recibidas.</p>
<p>Resultado final del plugin <a href="http://blog.davidrojo.es/wp-content/uploads/2011/06/customAutenticate.htm">customAutenticate</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.davidrojo.es/2011/06/custom-login-en-wordpress/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Efecto focos de hollywood en flash</title>
		<link>http://blog.davidrojo.es/2011/06/efecto-focos-de-hollywood-en-flash/</link>
		<comments>http://blog.davidrojo.es/2011/06/efecto-focos-de-hollywood-en-flash/#comments</comments>
		<pubDate>Tue, 14 Jun 2011 17:44:45 +0000</pubDate>
		<dc:creator>David</dc:creator>
				<category><![CDATA[Programación]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[programacion]]></category>

		<guid isPermaLink="false">http://blog.davidrojo.es/?p=280</guid>
		<description><![CDATA[Bueno, hace poco hice un efecto de focos en flash y quería compartirlo con todos. Básicamente vamos a usar un pequeño detalle que mucha gente suele pasar por alto a la hora de usar flash, y cuyas posibilidades pueden dar muy buenos resultados. En concreto hablo de “Blending” de las capas. Algo que se suele <a href='http://blog.davidrojo.es/2011/06/efecto-focos-de-hollywood-en-flash/'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>Bueno, hace poco hice un efecto de focos en flash y quería compartirlo con todos.</p>
<p>Básicamente vamos a usar un pequeño detalle que mucha gente suele pasar por alto a la hora de usar flash, y cuyas posibilidades pueden dar muy buenos resultados. En concreto hablo de “Blending” de las capas. Algo que se suele usar mucho en Photoshop pero que a veces en flash quedan olvidadas.</p>
<p>Para el ejemplo vamos a usar una imagen de fondo, y sobre ella vamos a crear unos focos que con el Blending adecuado proporcionaran el efecto deseado. Luego animaremos los focos para que parezcan más reales.</p>
<p>Para hacer el foco necesitaremos un cono, el cual su base debe de ser redonda. Para ello primero nos delimitaremos mediante guías realizando una cruz en nuestro documento. Luego, desde el centro de la cruz creamos un circulo (sin borde). Para hacer un circulo delimitado por centro-radio y que sea uniforme, debemos mantener pulsadas las teclas Alt (para que hacerlo centro-radio) y Shift (para que sea uniforme).</p>
<p><a href="http://blog.davidrojo.es/wp-content/uploads/2011/06/imagen1.png"><img class="aligncenter size-full wp-image-281 colorbox-280" title="imagen1" src="http://blog.davidrojo.es/wp-content/uploads/2011/06/imagen1.png" alt="" width="400" height="400" /></a></p>
<p>Después borraremos la mitad izquierda del círculo seleccionándolo con la herramienta “Selection Tool (V)” hasta la guía vertical.</p>
<p><a href="http://blog.davidrojo.es/wp-content/uploads/2011/06/imagen2.png"><img class="aligncenter size-full wp-image-282 colorbox-280" title="imagen2" src="http://blog.davidrojo.es/wp-content/uploads/2011/06/imagen2.png" alt="" width="400" height="400" /></a></p>
<p>Acto seguido rotaremos el medio círculo que nos queda. Para rotarlo tenemos que mover el centro de rotación al centro de nuestro círculo original, sino, no rotara como queremos.</p>
<p><a href="http://blog.davidrojo.es/wp-content/uploads/2011/06/imagen3.png"><img class="aligncenter size-full wp-image-283 colorbox-280" title="imagen3" src="http://blog.davidrojo.es/wp-content/uploads/2011/06/imagen3.png" alt="" width="400" height="400" /></a></p>
<p>Y por último eliminamos la parte que queda a la derecha de la guía vertical.</p>
<p><a href="http://blog.davidrojo.es/wp-content/uploads/2011/06/imagen4.png"><img class="aligncenter size-full wp-image-284 colorbox-280" title="imagen4" src="http://blog.davidrojo.es/wp-content/uploads/2011/06/imagen4.png" alt="" width="400" height="400" /></a></p>
<p>Y centramos la sección del círculo.</p>
<p><a href="http://blog.davidrojo.es/wp-content/uploads/2011/06/imagen5.png"><img class="aligncenter size-full wp-image-285 colorbox-280" title="imagen5" src="http://blog.davidrojo.es/wp-content/uploads/2011/06/imagen5.png" alt="" width="400" height="400" /></a></p>
<p>Ahora simplemente lo pintamos de blanco y creamos el Movie Clip “Foco”.</p>
<p>Una vez tengamos el MovieClip, podemos estirarlo para hacer un foco mas estilizado o achatarlo, según nos convenga.</p>
<p>Seleccionando el Movie Clip del foco, en Propiedades -&gt; Display, seleccionamos la opción Overlay. De esta manera conseguiremos el efecto de luminosidad que queremos. Jugando con la tinta y el alfa podemos conseguir focos de colores y de tonalidades más duras o más suaves</p>
<p><a href="http://blog.davidrojo.es/wp-content/uploads/2011/06/imagen6.png"><img class="aligncenter size-medium wp-image-286 colorbox-280" title="imagen6" src="http://blog.davidrojo.es/wp-content/uploads/2011/06/imagen6-300x165.png" alt="" width="300" height="165" /></a></p>
<p>Ahora lo único que nos queda es animarlo. Para ello seleccionamos el foco y le damos botón derecho -&gt; Convert to Symbol y creamos un nuevo símbolo “FocoAnimated”.</p>
<p>Entramos en el símbolo “FocoAnimated” y creamos un nuevo frame en el frame 35.</p>
<p><a href="http://blog.davidrojo.es/wp-content/uploads/2011/06/imagen7.png"><img class="aligncenter size-medium wp-image-287 colorbox-280" title="imagen7" src="http://blog.davidrojo.es/wp-content/uploads/2011/06/imagen7-300x300.png" alt="" width="300" height="300" /></a></p>
<p>Hacemos click derecho sobre la línea de frames y seleccionamos “Create Motion Tween”. El timeline se tiene que volver de color azul.</p>
<p>Ahora seleccionamos la pestaña “Motion editor” y realizaremos la animación. Aquí depende de cada uno como quiera animarlo, Se trata de hacer una rotación en Z con una determinada aceleración para hacer el efecto de movimiento del foco.</p>
<p>Haremos los siguientes valores:</p>
<p>Frame 1: RotationZ = -25</p>
<p>Frame 7: RotationZ = 0</p>
<p>Frame 14: RotationZ = 25</p>
<p>Frame 35: RotationZ = -25</p>
<p>Para los key frames 1, 14 y 35 hacermos click derecho sobre el punto en la línea del motion editor y seleccionaremos “smooth point”. Esto suavizará la animación</p>
<p><a href="http://blog.davidrojo.es/wp-content/uploads/2011/06/imagen8.png"><img class="aligncenter size-medium wp-image-288 colorbox-280" title="imagen8" src="http://blog.davidrojo.es/wp-content/uploads/2011/06/imagen8-300x92.png" alt="" width="300" height="92" /></a></p>
<p>Por último seleccionamos el foco y le aplicaremos un efecto blur de  25px de calidad alta, para que no se noten tanto los bordes del foco.</p>
<p>A partir de ahora, podemos duplicar el símbolo “FocoAnimated” para crear otros focos con otras animaciones y así combinarlos entre ellos para crear el efecto de varios focos.</p>
<p>
<object width="512" height="402">
<param name="movie" value="http://blog.davidrojo.es/wp-content/uploads/2011/06/HollywoodFocus.swf"></param>
<param name="quality" value="high"></param>
<param name="wmode" value="window"></param>
<param name="menu" value="false"></param>
<param name="bgcolor" value="#FFFFFF"></param>
<param name="allowScriptAccess" value="always"></param>
<embed type="application/x-shockwave-flash" width="512" height="402" src="http://blog.davidrojo.es/wp-content/uploads/2011/06/HollywoodFocus.swf" quality="high" bgcolor="#FFFFFF" wmode="window" menu="false" ></embed>
</object>
</p>
<p><a href="http://blog.davidrojo.es/wp-content/uploads/2011/06/HollywoodFocus.zip">Descargar código .fla</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.davidrojo.es/2011/06/efecto-focos-de-hollywood-en-flash/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Matar query en MySql</title>
		<link>http://blog.davidrojo.es/2011/05/matar-query-en-mysql/</link>
		<comments>http://blog.davidrojo.es/2011/05/matar-query-en-mysql/#comments</comments>
		<pubDate>Thu, 12 May 2011 22:59:01 +0000</pubDate>
		<dc:creator>David</dc:creator>
				<category><![CDATA[MySql]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[query]]></category>
		<category><![CDATA[trucos]]></category>

		<guid isPermaLink="false">http://blog.davidrojo.es/?p=266</guid>
		<description><![CDATA[¿A quien no le ha pasado que ha hecho una query en MySql y se le ha ido de las manos? Esa tipica query que se queda ahi en background corriendo y te deja la base de datos bloqueada con los locks en las tablas y no hay manera de hacer nada. Pues bien, hay <a href='http://blog.davidrojo.es/2011/05/matar-query-en-mysql/'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>¿A quien no le ha pasado que ha hecho una query en MySql y se le ha ido de las manos?</p>
<p>Esa tipica query que se queda ahi en background corriendo y te deja la base de datos bloqueada con los locks en las tablas y no hay manera de hacer nada. Pues bien, hay una manera muy sencilla de matar una query.</p>
<p>Simplemente primero tenemos que mostrar los procesos que se estan ejecutando, por supuesto debemos hacerlo con el mismo usuario que ha generado la query. Para ello haremos:</p>
<pre class="brush: plain; title: ; notranslate">SHOW PROCESSLIST</pre>
<p style="text-align: center;"><a href="http://blog.davidrojo.es/wp-content/uploads/2011/05/Untitled-3.png"></a><a href="http://blog.davidrojo.es/wp-content/uploads/2011/05/Untitled-31.png"><img class="aligncenter size-medium wp-image-274 colorbox-266" title="SHOW PROCESSLIST" src="http://blog.davidrojo.es/wp-content/uploads/2011/05/Untitled-31-300x61.png" alt="" width="300" height="61" /></a></p>
<p>Con esto veremos el ID de cada query que esta ejecutando el usuario. Ahora solo tenemos que matar el que queramos con el comando KILL</p>
<pre class="brush: plain; title: ; notranslate">KILL 1216094</pre>
<p>Y con esto ya habremos matado la query que nos está dando problemas.</p>
<p>Lógicamente si estamos acostumbrados a usar phpmyadmin, si la query bloquea la base de datos, seguramente nos bloqueara el phpmyadmin también, por lo que es recomendable usar otra herramienta para hacer esto, ya sea la <a title="Mysql Workbench" href="http://wb.mysql.com/" target="_blank">GUI Workbench de MySql</a> o desde la propia consola.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.davidrojo.es/2011/05/matar-query-en-mysql/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Selectividad ASES</title>
		<link>http://blog.davidrojo.es/2011/05/selectividad-ases/</link>
		<comments>http://blog.davidrojo.es/2011/05/selectividad-ases/#comments</comments>
		<pubDate>Sat, 07 May 2011 10:49:31 +0000</pubDate>
		<dc:creator>David</dc:creator>
				<category><![CDATA[Proyectos]]></category>

		<guid isPermaLink="false">http://blog.davidrojo.es/?p=253</guid>
		<description><![CDATA[Proyecto para la Academia ASES para realizar un portal integrado en Facebook para preparar la selectividad 2011. En la aplicación integrada en Facebook, se puede descargar los exámenes solucionados en pdf, y las colecciones de problemas. Los alumnos pueden solicitar correcciones de las colecciones de problemas y reciben una video explicación de cada apartado solicitado.]]></description>
			<content:encoded><![CDATA[
<a href='http://blog.davidrojo.es/2011/05/selectividad-ases/colecciones/' title='colecciones'><img width="150" height="150" src="http://blog.davidrojo.es/wp-content/uploads/2011/05/colecciones-150x150.png" class="attachment-thumbnail colorbox-253" alt="colecciones" title="colecciones" /></a>
<a href='http://blog.davidrojo.es/2011/05/selectividad-ases/convocatorias/' title='convocatorias'><img width="150" height="150" src="http://blog.davidrojo.es/wp-content/uploads/2011/05/convocatorias-150x150.png" class="attachment-thumbnail colorbox-253" alt="convocatorias" title="convocatorias" /></a>
<a href='http://blog.davidrojo.es/2011/05/selectividad-ases/dudas/' title='dudas'><img width="150" height="150" src="http://blog.davidrojo.es/wp-content/uploads/2011/05/dudas-150x150.png" class="attachment-thumbnail colorbox-253" alt="dudas" title="dudas" /></a>
<a href='http://blog.davidrojo.es/2011/05/selectividad-ases/home-2/' title='home'><img width="150" height="150" src="http://blog.davidrojo.es/wp-content/uploads/2011/05/home-150x150.png" class="attachment-thumbnail colorbox-253" alt="home" title="home" /></a>
<a href='http://blog.davidrojo.es/2011/05/selectividad-ases/info/' title='info'><img width="150" height="150" src="http://blog.davidrojo.es/wp-content/uploads/2011/05/info-150x150.png" class="attachment-thumbnail colorbox-253" alt="info" title="info" /></a>
<a href='http://blog.davidrojo.es/2011/05/selectividad-ases/muro/' title='muro'><img width="150" height="150" src="http://blog.davidrojo.es/wp-content/uploads/2011/05/muro-150x150.png" class="attachment-thumbnail colorbox-253" alt="muro" title="muro" /></a>
<a href='http://blog.davidrojo.es/2011/05/selectividad-ases/video-demo/' title='video demo'><img width="150" height="150" src="http://blog.davidrojo.es/wp-content/uploads/2011/05/video-demo-150x150.png" class="attachment-thumbnail colorbox-253" alt="video demo" title="video demo" /></a>
<a href='http://blog.davidrojo.es/2011/05/selectividad-ases/facebook-profile/' title='facebook profile'><img width="150" height="150" src="http://blog.davidrojo.es/wp-content/uploads/2011/05/facebook-profile-150x150.png" class="attachment-thumbnail colorbox-253" alt="facebook profile" title="facebook profile" /></a>

<p>Proyecto para la Academia ASES para realizar un portal integrado en Facebook para preparar la selectividad 2011.</p>
<p>En la aplicación integrada en Facebook, se puede descargar los exámenes solucionados en pdf, y las colecciones de problemas.</p>
<p>Los alumnos pueden solicitar correcciones de las colecciones de problemas y reciben una video explicación de cada apartado solicitado.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.davidrojo.es/2011/05/selectividad-ases/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Escalando imágnes con PHP (GD Graphics Library)</title>
		<link>http://blog.davidrojo.es/2011/05/redimensionar-imagnes-con-php/</link>
		<comments>http://blog.davidrojo.es/2011/05/redimensionar-imagnes-con-php/#comments</comments>
		<pubDate>Tue, 03 May 2011 16:42:56 +0000</pubDate>
		<dc:creator>David</dc:creator>
				<category><![CDATA[Programación]]></category>
		<category><![CDATA[gd graphics library]]></category>
		<category><![CDATA[imágenes]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programacion]]></category>

		<guid isPermaLink="false">http://blog.davidrojo.es/?p=243</guid>
		<description><![CDATA[Bueno, hace unos días publiqué una entrada para redimensionar imágenes con PHP usando Imagick, como muchos servidores no disponen de esta libreria y es problable que no podamos instalarla, voy a mostraros como redimensionar imágenes usando la librería GD que es la más común y que probablemente tengamos instalada en nuestro servidor. Como no tengo <a href='http://blog.davidrojo.es/2011/05/redimensionar-imagnes-con-php/'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>Bueno, hace unos días publiqué una entrada para <a title="Escalando imágenes con PHP" href="http://blog.davidrojo.es/2011/04/escalando-imagenes-con-php/">redimensionar imágenes con PHP usando Imagick</a>, como muchos servidores no disponen de esta libreria y es problable que no podamos instalarla, voy a mostraros como redimensionar imágenes usando la librería GD que es la más común y que probablemente tengamos instalada en nuestro servidor.</p>
<p>Como no tengo tiempo de ponerme a explicar todo, lo que voy a hacer es publicaros una clase con todas las funciones necesarias, compatible con archivos png, jpg y gif y con soporte para transparencias. Cualquier duda me la podéis comentar a través de los comentarios.</p>
<p>La clase la he llamado Image (en un alarde de originalidad) y contiene los siguientes métodos:</p>
<pre class="brush: php; title: ; notranslate">public function Image($src)</pre>
<p>Constructor. Crea una imágen a partir del $src especificado</p>
<pre class="brush: php; title: ; notranslate">public function loadImage($src)</pre>
<p>Carga una imágen a partir del $src especificado.</p>
<pre class="brush: php; title: ; notranslate">public function setQuality($q)</pre>
<p>0 &lt;= $q &lt;= 100. Establece la calidad de la imágen a generar. Solo aplicable a imágenes jpg</p>
<pre class="brush: php; title: ; notranslate">public function setOutput($type)</pre>
<p>Establece el tipo de salida de la imágen. Por defecto es el mismo tipo que la imágen de entrada. Valores aceptados: &#8220;image/jpeg&#8221;, &#8220;image/gif&#8221;, &#8220;image/png&#8221;</p>
<pre class="brush: php; title: ; notranslate">public function resize($width = &quot;&quot;, $height = &quot;&quot;)</pre>
<p>Reescala la imàgen cargada previamente para que encaje en un rectángulo de $width x $height sin perder las proporciones originales.</p>
<pre class="brush: php; title: ; notranslate">public function printImage()</pre>
<p>Imprime por el canal estándar la imagen resultante con el header específico.</p>
<pre class="brush: php; title: ; notranslate">public function saveImage($saveFile)</pre>
<p>Guarda la imágen en el archivo especificado por $saveFile.</p>
<pre class="brush: php; title: ; notranslate">public function setWaterMark($waterSrc, $left, $top, $right = &quot;&quot;, $bottom = &quot;&quot;)</pre>
<p>Añade la imagen especificada en la ruta $waterSrc a la imagen cargada. en la posición $left &#8211; $top. En caso de especificar $right o $bottom sobreescriben los valores de $left y $top.</p>
<p>Así pues para generar una imagen y reescalarla tendremos que hacer lo siguiente:</p>
<pre class="brush: php; title: ; notranslate">include (&quot;Image.php&quot;);
$im = new Image(PATH_TO_IMAGE);
$im-&gt;resize(200, 200);
$im-&gt;printImage();</pre>
<p>Si queremos añadirle una marca de agua simplemente tendremos que añadir la llamada a la función setWaterMark.</p>
<pre class="brush: php; title: ; notranslate">$im-&gt;setWaterMark(PATH_TO_WATERMARK, 0, 0, 20, 20);</pre>
<p>Y si queremos guardar la imágen en el disco duro:</p>
<pre class="brush: php; title: ; notranslate">$im-&gt;saveImage(PATH_TO_SAVE);</pre>
<p>Podéis ver un ejemplo del resultado <a title="Ejemplo Imagen" href="http://blog.davidrojo.es/Files/testCodes/Image/index.html" target="_blank">aquí</a></p>
<p><a title="Image" href="http://blog.davidrojo.es/Files/testCodes/Image/Image-source..htm" target="_blank">Ver código fuente</a> | <a title="Image" href="http://blog.davidrojo.es/Files/testCodes/Image.zip" target="_blank">Descargar código de ejemplo</a>.</p>
<p>El código de la clase Image lo podéis encontrar en la carpeta src. Los ficheros test-image y test-watermark muestran el funcionamiento de la clase Image</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.davidrojo.es/2011/05/redimensionar-imagnes-con-php/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Imprimir un array formateado en PHP</title>
		<link>http://blog.davidrojo.es/2011/04/imprimir-un-array-formateado/</link>
		<comments>http://blog.davidrojo.es/2011/04/imprimir-un-array-formateado/#comments</comments>
		<pubDate>Thu, 21 Apr 2011 18:25:33 +0000</pubDate>
		<dc:creator>David</dc:creator>
				<category><![CDATA[Programación]]></category>
		<category><![CDATA[array]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[proramación]]></category>

		<guid isPermaLink="false">http://blog.davidrojo.es/?p=228</guid>
		<description><![CDATA[El otro día un amigo me preguntaba como ver la estructura de un array en PHP.La solución es muy sencilla, usar la función print_r. Mi amigo al cabo de un par de minutos me comentaba que sí, que le había imprimido el array, pero que no se enteraba de nada, el array era demasiado grande <a href='http://blog.davidrojo.es/2011/04/imprimir-un-array-formateado/'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>El otro día un amigo me preguntaba como ver la estructura de un array en PHP.La solución es muy sencilla, usar la función <a title="print_r" href="http://php.net/manual/es/function.print-r.php">print_r</a>.</p>
<p>Mi amigo al cabo de un par de minutos me comentaba que sí, que le había imprimido el array, pero que no se enteraba de nada, el array era demasiado grande y no veía la estructura que tenía. Para solucionar este problema, debemos usar el tag &lt;pre&gt; de html. Éste tag es especialmente útil para este caso, ya que lo que hace, básicamente, es mostrar el texto tal cual, con todos los espacios y saltos de línea que tenga el código HTML. Podemos emular el comportamiento de éste tag usando css en cualquier parte de nuestra página:</p>
<pre class="brush: css; title: ; notranslate">
   white-space: pre-wrap;
</pre>
<p>Por lo tanto si queremos imprimir un array conservando el formato deberemos hacer:</p>
<pre class="brush: php; title: ; notranslate">
   echo '&lt;pre&gt;';
   print_r($array);
   echo '&lt;/pre&gt;';
</pre>
<p>Bién, hasta aquí todo correcto, ahora, mi consejo es encapsular todo esto en una funcuón, ya que utilizaremos este código muy a menudo, sobre todo para debugar. Yo personalmente la llamo printr, sin el _ en medio, me es muy fácil de recordar:</p>
<pre class="brush: php; title: ; notranslate">

function printr($array){
    echo '&lt;pre&gt;';
    print_r($array);
    echo '&lt;/pre&gt;';
}
</pre>
<p>Hay un pequeño detalle de la función print_r que mucha gente pasa por alto, y es su segundo parámetro. Podemos añadirle un segundo parámetro booleano, que si es true, entonces en vez de imprimir el array, lo que hace es retornarlo como un string, así que podemos añadirlo a nuestra función para que se comporte exáctamente igual.</p>
<pre class="brush: php; title: ; notranslate">

function printr($array, $print = true){
    if ($print) return print_r($array, true);
    else echo '&lt;pre&gt;'.print_r($array, true).'&lt;/pre&gt;';
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.davidrojo.es/2011/04/imprimir-un-array-formateado/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

