<?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>Codigo Manso &#187; PHP</title>
	<atom:link href="http://www.codigomanso.com/es/tag/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.codigomanso.com</link>
	<description>Programación, informática y tecnología</description>
	<lastBuildDate>Thu, 09 Sep 2010 06:20:10 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>http_build_query para Python</title>
		<link>http://www.codigomanso.com/es/2010/04/http_build_query-para-python/</link>
		<comments>http://www.codigomanso.com/es/2010/04/http_build_query-para-python/#comments</comments>
		<pubDate>Thu, 22 Apr 2010 21:00:04 +0000</pubDate>
		<dc:creator>Pau Sanchez</dc:creator>
				<category><![CDATA[Programacion]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[http_build_query]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.codigomanso.com/es/?p=854</guid>
		<description><![CDATA[Para quien le sirva, me he pasado un rato haciendo una función en python que fuera equivalente a http_build_query de PHP.
##
# Mimics the behaviour of http_build_query PHP function
# This method can be useful for sending data to flash applications
##################################################
def http_build_query(params, topkey = ''):
  from urllib import quote

  if len(params) == 0:
   [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Para quien le sirva, me he pasado un rato haciendo una función en python que fuera equivalente a http_build_query de PHP.</p>
<pre><code>##
# Mimics the behaviour of http_build_query PHP function
# This method can be useful for sending data to flash applications
##################################################
def http_build_query(params, topkey = ''):
  from urllib import quote

  if len(params) == 0:
    return ""

  result = ""

  # is a dictionary?
  if type (params) is dict:
    for key in params.keys():
      newkey = quote (key)
      if topkey != '':
        newkey = topkey + quote('[' + key + ']')

      if type(params[key]) is dict:
        result += http_build_query (params[key], newkey)

      elif type(params[key]) is list:
        i = 0
        for val in params[key]:
          result += newkey + quote('[' + str(i) + ']') + "=" + quote(str(val)) + "&amp;"
          i = i + 1

      # boolean should have special treatment as well
      elif type(params[key]) is bool:
        result += newkey + "=" + quote (str(int(params[key]))) + "&amp;"

      # assume string (integers and floats work well)
      else:
        result += newkey + "=" + quote (str(params[key])) + "&amp;"

  # remove the last '&amp;'
  if (result) and (topkey == '') and (result[-1] == '&amp;'):
    result = result[:-1]

  return result</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.codigomanso.com/es/2010/04/http_build_query-para-python/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Truco Manso: Detectar el sistema operativo en PHP</title>
		<link>http://www.codigomanso.com/es/2010/04/truco-manso-detectar-el-sistema-operativo-en-php/</link>
		<comments>http://www.codigomanso.com/es/2010/04/truco-manso-detectar-el-sistema-operativo-en-php/#comments</comments>
		<pubDate>Thu, 08 Apr 2010 09:36:39 +0000</pubDate>
		<dc:creator>Pau Sanchez</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programacion]]></category>
		<category><![CDATA[truco manso]]></category>
		<category><![CDATA[sistema operativo]]></category>
		<category><![CDATA[so]]></category>

		<guid isPermaLink="false">http://www.codigomanso.com/es/?p=779</guid>
		<description><![CDATA[Los motivos pueden ser diversos, y se podría abrir un debate. En cualquier caso yo no voy a entrar en los porqués, pero a veces resulta útil saber el sistema operativo en el que corre la web, ya que dependiendo de éste, se pueden realizar algunas optimizaciones, o ejecutar algunos u otros comandos, o símplemente [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Los motivos pueden ser diversos, y se podría abrir un debate. En cualquier caso yo no voy a entrar en los porqués, pero a veces resulta útil saber el sistema operativo en el que corre la web, ya que dependiendo de éste, se pueden realizar algunas optimizaciones, o ejecutar algunos u otros comandos, o símplemente puede resultar interesante a nivel informativo, en cualquier caso, lo normal es que no te haga falta jamás saber el sistema operativo en el que está ejecutandose tu código PHP.</p>
<p style="text-align: justify;">Suponiendo que te hace falta, hay dos formas de saber el sistema operativo. La primera, y más completa, es mediante la función <a href=" http://php.net/manual/en/function.php-uname.php" target="_blank"><em>php_uname</em></a>. La función php_uname es similar al comando uname de linux, y con esta podemos saber el sistema operativo y la versión del mismo, el número de release del SO, el nombre del host y la arquitectura del ordenador. Completito completito.</p>
<p style="text-align: justify;">Por otra parte, si no queremos calentarnos la cabeza, y sólo queremos saber el sistema operativo, se puede usar la constante <em>PHP_OS</em>. Más sencillo, pero en la mayoría de los casos será suficiente (el equivalente sería <em><strong>php_uname(&#8217;s&#8217;)</strong></em>).</p>
<p style="text-align: justify;">
<pre><code>echo php_uname() . "\n";
echo PHP_OS . "\n";</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.codigomanso.com/es/2010/04/truco-manso-detectar-el-sistema-operativo-en-php/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>TCPDF excelente libreria para generar PDFs en PHP</title>
		<link>http://www.codigomanso.com/es/2009/12/tcpdf-excelente-libreria-para-generar-pdfs-en-php/</link>
		<comments>http://www.codigomanso.com/es/2009/12/tcpdf-excelente-libreria-para-generar-pdfs-en-php/#comments</comments>
		<pubDate>Mon, 07 Dec 2009 09:10:55 +0000</pubDate>
		<dc:creator>Pau Sanchez</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[pdf]]></category>
		<category><![CDATA[php-pdf]]></category>

		<guid isPermaLink="false">http://www.codigomanso.com/es/?p=797</guid>
		<description><![CDATA[El otro día estuve investigando el tema de generar PDFs con PHP.
Lo primero que me vino a la cabeza fué la extensión de PDFlib que incluye PHP desde la versión 4. El problema de esta versión es que me parecía muy a bajo nivel, y tampoco tenía ni idea de por donde empezar.
La lista de [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">El otro día estuve investigando el tema de generar PDFs con PHP.</p>
<p style="text-align: justify;">Lo primero que me vino a la cabeza fué la <a href="http://php.net/manual/en/book.pdf.php">extensión de PDFlib</a> que incluye PHP desde la versión 4. El problema de esta versión es que me parecía muy a bajo nivel, y tampoco tenía ni idea de por donde empezar.</p>
<p style="text-align: justify;">La <a href="http://www.php.net/manual/en/ref.pdf.php">lista de funciones de PDFlib que incorpora PHP</a> es bastante extensa, y seguramente se puede hacer de todo, pero no quería estar escribiendo cientos de lineas para hacer una chorrada de PDF, símplemente quería ponerle un fondo y escribir cuatro cosas.</p>
<p style="text-align: justify;">En fin, que buscando más información, acabé encontrándome con la librería <a href="http://www.tcpdf.org">TCPDF</a> que parecía muchísimo más completa, y más sencilla de usar. Realmente no se si es más sencilla o no, porque al final no he hecho nada con la extensión de PDFlib, pero <a href="http://www.tecnick.com/public/code/cp_dpage.php?aiocp_dp=tcpdf_examples">TCPDF tiene muchos ejemplos.</a> Hay ejemplos supersencillos de muchas cosas, con lo que hacer un PDF se convierte prácticamente en copiar y pegar de aquí y allá.</p>
<p style="text-align: justify;">La verdad es que con esta librería hice un prototipo de lo que quería hacer en 15 minutos. Puedes pasarle el código en formato HTML y luego la librería lo formatea internamente en el documento. Esto hace que no te tengas que calentar mucho la cabeza.</p>
<p style="text-align: justify;">La única &#8220;pega&#8221; que le veo, es que ocupa unos 10MB comprimida en zip, lo que son unos 16 megas una vez descomprimida.  En cualquier caso, la mayor parte del tamaño no es por la librería en sí, si no por que dentro lleva ya fuentes tipográficas, la documentación, y ejemplos. Si eliminamos las fuentes que no nos hacen falta y la documentación, se puede quedar en poco más de 1 megabyte descomprimida. Vamos, de lujo.</p>
<p style="text-align: justify;">Más información sobre esta librería en <a href="http://www.tcpdf.org">www.tcpdf.org</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.codigomanso.com/es/2009/12/tcpdf-excelente-libreria-para-generar-pdfs-en-php/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>PHP se supera a si mismo</title>
		<link>http://www.codigomanso.com/es/2009/11/php-se-supera-a-si-mismo/</link>
		<comments>http://www.codigomanso.com/es/2009/11/php-se-supera-a-si-mismo/#comments</comments>
		<pubDate>Fri, 06 Nov 2009 09:20:29 +0000</pubDate>
		<dc:creator>Pau Sanchez</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[goto]]></category>
		<category><![CDATA[karmic]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[php 5.3]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://www.codigomanso.com/es/?p=748</guid>
		<description><![CDATA[Resulta que andaba yo buscando cómo instalar PHP 5.3 en el nuevo ubuntu karmic, porque me simplificaría las cosas usar la nueva funcionalidad de late static binding, y resulta que me acabo de encontrar de otro gran feature introducido en PHP 5.3 y que PHP no tenía&#8230;
el GOTO
Resulta increible cómo puede ser que introduzcan en [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Resulta que andaba yo buscando cómo instalar PHP 5.3 en el nuevo ubuntu karmic, porque me simplificaría las cosas usar la nueva funcionalidad de late static binding, y resulta que me acabo de encontrar de otro gran feature introducido en PHP 5.3 y que PHP no tenía&#8230;</p>
<p style="text-align: center;">el <strong>GOTO</strong></p>
<p style="text-align: justify;">Resulta increible cómo puede ser que introduzcan en PHP cosas de tan alto nivel, y de tan bajo nivel a la vez&#8230; deben de haber tenido bastante presión por parte de la gente, porque sino no me lo explico&#8230;</p>
<p style="text-align: justify;"><a href="http://us.php.net/goto" target="_blank">En la documentación de PHP del goto</a> se puede ver que las cosas se las toman con humor:</p>
<p style="text-align: justify;"><a href="http://us.php.net/goto" target="_blank"><img class="aligncenter" title="Cuidado que el dinosaurio te come" src="http://us.php.net/manual/en/images/0baa1b9fae6aec55bbb73037f3016001-xkcd-goto.png" alt="" width="516" height="140" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.codigomanso.com/es/2009/11/php-se-supera-a-si-mismo/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Detectar en PHP si un gif es animado</title>
		<link>http://www.codigomanso.com/es/2009/06/detect-an-animated-gif-in-php/</link>
		<comments>http://www.codigomanso.com/es/2009/06/detect-an-animated-gif-in-php/#comments</comments>
		<pubDate>Sun, 28 Jun 2009 19:50:33 +0000</pubDate>
		<dc:creator>Pau Sanchez</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programacion]]></category>
		<category><![CDATA[animado]]></category>
		<category><![CDATA[gif]]></category>

		<guid isPermaLink="false">http://www.codigomanso.com/es/?p=679</guid>
		<description><![CDATA[La siguiente función sirve para detectar si un GIF es animado o no (tiene más de 1 frame).
  function isAnimatedGif($filename)
  {
    $filecontents=file_get_contents($filename);

    $str_loc=0;
    $count=0;

    # There is no point in continuing after we find a 2nd frame
    while [...]]]></description>
			<content:encoded><![CDATA[<p>La siguiente función sirve para detectar si un GIF es animado o no (tiene más de 1 frame).</p>
<pre><code>  function isAnimatedGif($filename)
  {
    $filecontents=file_get_contents($filename);

    $str_loc=0;
    $count=0;

    # There is no point in continuing after we find a 2nd frame
    while ($count &lt; 2)
    {
      $where1=strpos($filecontents,"\x00\x21\xF9\x04", $str_loc);
      if ($where1 === FALSE) {
        break;
      }

      $str_loc = $where1+1;
      $where2  = strpos($filecontents,"\x00\x2C",$str_loc);
      if ($where2 === FALSE) {
        break;
      }
      else {
        if ($where1+8 == $where2) {
          $count++;
        }
        $str_loc = $where2+1;
      }
    }

    // gif is animated when it has two or more frames
    return ($count &gt;= 2);
  }</code></pre>
<p>También está la siguiente alternativa, más compacta que la anterior:<br />
<code>&lt;pre&gt;<br />
function isAnimatedGif($filename) {<br />
    return (bool)preg_match('#(\x00\x21\xF9\x04.{4}\x00\x2C.*){2,}#s', file_get_contents($filename));<br />
}</code></pre>
<p>El código lo he modificado minimamente a partir de lo que he encontrado en los comentarios de <a href="http://es2.php.net/manual/en/function.imagecreatefromgif.php">http://es2.php.net/manual/en/function.imagecreatefromgif.php</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.codigomanso.com/es/2009/06/detect-an-animated-gif-in-php/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Escalar una imagen manteniendo el aspecto</title>
		<link>http://www.codigomanso.com/es/2009/03/escalar-una-imagen-manteniendo-el-aspecto/</link>
		<comments>http://www.codigomanso.com/es/2009/03/escalar-una-imagen-manteniendo-el-aspecto/#comments</comments>
		<pubDate>Fri, 27 Mar 2009 20:10:52 +0000</pubDate>
		<dc:creator>Pau Sanchez</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[aspect ratio]]></category>
		<category><![CDATA[aspecto]]></category>
		<category><![CDATA[escalar]]></category>
		<category><![CDATA[imagenes]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.codigomanso.com/es/?p=621</guid>
		<description><![CDATA[Muchas veces es necesario escalar una imagen para que se mantenga dentro de unos límites y pueda visualizarse correctamente. Es mucho mejor si la imagen no se deforma. En estos casos hay que hacer un escalado manteniendo el aspect ratio.
Hoy día hay cientos de librerias para cualquier lenguaje que realizan un escalado. La única pregunta [...]]]></description>
			<content:encoded><![CDATA[<p>Muchas veces es necesario escalar una imagen para que se mantenga dentro de unos límites y pueda visualizarse correctamente. Es mucho mejor si la imagen no se deforma. En estos casos hay que hacer un escalado manteniendo el aspect ratio.</p>
<p>Hoy día hay cientos de librerias para cualquier lenguaje que realizan un escalado. La única pregunta es, ¿cuales deben ser el nuevo ancho y largo de la imagen?</p>
<p>A continuación el código mágico que está probado en javascript, pero que debe funcionar en PHP, python, java, perl, C, y lo que le pongas por delate <img src='http://www.codigomanso.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<pre><code>if (w &lt; h) {
  h = (h * maxWidth) / w;
  w = maxWidth;
}
else {
  w = (w * maxHeight) / h;
  h = maxHeight;
}</code></pre>
<p><b>w</b> representa el ancho o width de la imagen</p>
<p><b>h</b> representa el alto o height de la imagen</p>
<p><b>maxWidth</b> la anchura máxima del área en la que se quiere meter la imagen</p>
<p><b>maxHeight</b> la altura máxima del área en la que se quiere meter la imagen</p>
<p>Como ejemplo final, aunque es prácticamente copy paste, imaginad que quereis meter una imágen de tamaño (w, h) en un área de 640&#215;480:</p>
<pre><code>var maxWidth = 640, maxHeight = 480;
if (w &gt; maxWidth || h &gt; maxHeight) {
  if (w &lt; h) {
    h = (h * maxWidth) / w;
    w = maxWidth;
  }
  else {
    w = (w * maxHeight) / h;
    h = maxHeight;
  }
}</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.codigomanso.com/es/2009/03/escalar-una-imagen-manteniendo-el-aspecto/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Convertir una cadena UTF-8 en un array en PHP</title>
		<link>http://www.codigomanso.com/es/2009/02/convert-utf8-string-to-array-in-php/</link>
		<comments>http://www.codigomanso.com/es/2009/02/convert-utf8-string-to-array-in-php/#comments</comments>
		<pubDate>Sun, 22 Feb 2009 10:19:10 +0000</pubDate>
		<dc:creator>Pau Sanchez</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programacion]]></category>
		<category><![CDATA[i18n]]></category>
		<category><![CDATA[internacionalización]]></category>
		<category><![CDATA[utf-8]]></category>

		<guid isPermaLink="false">http://www.codigomanso.com/es/?p=578</guid>
		<description><![CDATA[Mientras llega y no llega PHP 6, con esas mejoras entre las que se encuentra el soporte nativo de UTF-8, algunos tenemos que seguir programando.
Creo que próximamente compartiré la clase de manejo de cadenas que estoy desarrollando, y que soporta 100% utf-8.
De momento voy a compartir una función, que si bien no es la más [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Mientras llega y no llega PHP 6, con esas mejoras entre las que se encuentra el soporte nativo de UTF-8, algunos tenemos que seguir programando.</p>
<p style="text-align: justify;">Creo que próximamente compartiré la clase de manejo de cadenas que estoy desarrollando, y que soporta 100% utf-8.</p>
<p style="text-align: justify;">De momento voy a compartir una función, que si bien no es la más aconsejable puesto que los arrays en PHP consumen MUCHOS recursos, creo que facilita el uso de cadenas UTF-8, pues se les puede dar el mismo tratamiento que a una cadena normal.</p>
<p style="text-align: justify;">Convertir una cadena UTF-8 a un array tiene 2 grandes ventajas:</p>
<ul style="text-align: justify;">
<li>cada elemento del array representa un único caracter</li>
<li><strong>count</strong> sobre el array será equivalente a <strong>mb_strlen</strong> sobre la cadena</li>
</ul>
<p style="text-align: justify;">La gran destventaja son los tiempos de conversión y el consumo de memoria, al estar usando un array.</p>
<p style="text-align: justify;">Ayer básicamente programé 2 funciones y <a href="http://uk3.php.net/manual/en/function.mb-split.php#80046" target="_blank">cojí prestado un ejemplo</a> que había puesto un usuario en la documentación de PHP.</p>
<p style="text-align: justify;">Las tres versiones de estas funciones las podeis ver a continuación:</p>
<pre><code>function getCharArray1 ($jstring)
{
  $len = mb_strlen ($jstring, 'UTF-8');
  if (mb_strlen ($jstring, 'UTF-8') == 0)
    return array();

  $ret = array();
  for ($i = 0; $i &lt; $len; $i++) {
    $char = mb_substr ($jstring, $i, 1, 'UTF-8');
    array_push ($ret, $char);
  }

  return $ret;
}

// code from: http://uk3.php.net/manual/en/function.mb-split.php#80046
function getCharArray2 ($jstring)
{
  $len = mb_strlen ($jstring, 'UTF-8');
  if (mb_strlen ($jstring, 'UTF-8') == 0)
    return array();

  while ($len) {
    $ret[]  = mb_substr($jstring,0,1,"UTF-8");
    $jstring = mb_substr($jstring,1,$len,"UTF-8");
    $len = mb_strlen($jstring);
  }
  return $ret;
}

// using mb_check_encoding instead of mb_substr <img src='http://www.codigomanso.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />
function getCharArray3 ($jstring)
{
  if (mb_strlen ($jstring, 'UTF-8') == 0)
    return array();

  $ret  = array ();
  $alen = strlen ($jstring);
  $char = '';
  for ($i = 0; $i &lt; $alen; $i++) {
    $char .= $jstring[$i];
    if (mb_check_encoding ($char, 'UTF-8')) {
      array_push ($ret, $char);
      $char = '';
    }
  }

  return $ret;
}</code></pre>
<p style="text-align: justify;">La función más rápida es la última, que utiliza un pequeño truco que se me ocurrió.</p>
<p style="text-align: justify;">La gráfica representa los tiempos de ejecución de cada una de estas funciones para una serie de iteraciones sobre una cadena notablemente larga.
</p>
<p><script type="text/javascript" src="http://www.codigomanso.com/archives/open-flash-chart/swfobject.js"></script><br />
<script type="text/javascript">
  swfobject.embedSWF(
    "http://www.codigomanso.com/archives/open-flash-chart/open-flash-chart.swf",
    "performance_chart", 
    "512", "384",
    "9.0.0",
    "expressInstall.swf",
    {"data-file":"http://www.codigomanso.com/archives/phpscripts/bench_getCharArray.txt"}
  );
</script></p>
<div id="performance_chart"></div>
<p><strong> Leyenda:</strong></p>
<ul>
<li><strong style="color:red;">getCharArray1:</strong> en rojo</li>
<li><strong style="color:green;">getCharArray2:</strong> en verde</li>
<li><strong style="color:blue;">getCharArray3:</strong> en azul</li>
</ul>
<p>Como se puede comprobar, <b>getCharArray3</b> es la más rápida (sobre 4x más que getCharArray1 y 6x más que getCharArray2).</p>
<p>Finalmente, aquí teneis el <a href="http://www.codigomanso.com/archives/phpscripts/bench_getCharArray.php.txt">enlace al script de benchmark</a> que he usado para obtener esa gráfica.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.codigomanso.com/es/2009/02/convert-utf8-string-to-array-in-php/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Tokenizador superrápido en PHP</title>
		<link>http://www.codigomanso.com/es/2008/11/tokenizador-superrapido-en-php/</link>
		<comments>http://www.codigomanso.com/es/2008/11/tokenizador-superrapido-en-php/#comments</comments>
		<pubDate>Thu, 27 Nov 2008 19:00:25 +0000</pubDate>
		<dc:creator>Pau Sanchez</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[analizador lexico]]></category>
		<category><![CDATA[analizador sintactico]]></category>
		<category><![CDATA[lexer php]]></category>
		<category><![CDATA[parser]]></category>
		<category><![CDATA[php tokenizer]]></category>
		<category><![CDATA[tokenizador]]></category>
		<category><![CDATA[tokenizer]]></category>

		<guid isPermaLink="false">http://www.codigomanso.com/?p=162</guid>
		<description><![CDATA[Actualmente, como parte de un par de proyectos que estoy desarrollando, estoy trabajando en una especie de libreria/framework de PHP (no me acaba de gustar el termino de framework y trato de que sea más libreria que framework).
El caso es que para algunos de los componentes necesitaba hacer un parser (también llamado analizador sintáctico), y [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Actualmente, como parte de un par de proyectos que estoy desarrollando, estoy trabajando en una especie de libreria/framework de PHP (no me acaba de gustar el termino de framework y trato de que sea más libreria que framework).</p>
<p style="text-align: justify;">El caso es que para algunos de los componentes necesitaba hacer un parser (<a href="http://es.wikipedia.org/wiki/Analizador_sint%C3%A1ctico" target="_blank">también llamado analizador sintáctico</a>), y para el parser necesitaba un tokenizador en PHP (tokenizador = <a href="http://es.wikipedia.org/wiki/Analizador_l%C3%A9xico" target="_blank">analizador léxico o lexer</a>), y claro está, cuanto más rápido funcione todo mejor (que PHP es interpretado y ya se sabe).</p>
<p style="text-align: justify;">Total, que había dos opciones: o hacerlo desde 0, usando las funciones de string que trae PHP (una opción que se plantea lenta); o bien usar la función <strong>token_get_all</strong> que está disponible desde la versión 4.2.0.</p>
<p style="text-align: justify;">Personalmente, he preferido usar <strong>token_get_all</strong>, aunque esta funcion sea, en si misma, un parser de código de PHP. Lo que he hecho es una clase que encapsula la llamada a esta función y devuelve una lista de token ids vs texto.</p>
<p style="text-align: justify;">El truco para llamar a <strong>token_get_all</strong> es añadir <strong>&#8220;&lt;?php &#8220;</strong> y <strong>&#8220;?&gt;&#8221;</strong> al principio y final de la cadena que se desea tokenizar (probablemente el &#8220;?&gt;&#8221; del final no haga falta).</p>
<p style="text-align: justify;">Si los tokens necesarios para el parser es un subconjunto de los tokens que soporta PHP, entonces no hay ningún problema con usar este método, si no es así, habrá que currarselo un poco más (y como en mi caso sí se trata de un subconjunto, dejo ese tema zanjado en este punto).</p>
<p style="text-align: justify;">El problema de la función <strong>token_get_all</strong> es que devuelve un array no demasiado normalizado. A veces devuelve un único item (el texto propio del token), mientras que otras veces devuelve un par de elementos en un array (el primero es el token id y el segundo el texto).</p>
<p style="text-align: left;">Al tema:</p>
<pre><code>class jtokenizer {
  const TK_UNKNOWN  = 0x0000;
  const TK_ID       = 0x0001;
  const TK_STRING   = 0x0002;

  const TK_PLUS     = 0x0003;
  const TK_MINUS    = 0x0004;

  // ...

  public static function tokenize ($string) {
    $tokens = array();
    $phptokens = token_get_all ('&lt;?php ' . $string . '?&gt;');

    foreach ($phptokens as $ptoken) {
      $id = self::TK_UNKNOWN;
      if (is_string ($ptoken)) {
        $text = $ptoken;
        switch ($ptoken) {
          case '+': $id = self::TK_PLUS;  break;
          case '-': $id = self::TK_MINUS; break;

          ////////////////////////////////////////
          // Add more tokens here!
          // E.g: '.', ',', ';', ':', '=', ...
          ////////////////////////////////////////

          default: /** handle error here! */ break;
        }
      }
      else { // this should be an array (tokenid, text)
        list ($tokenid, $text) = $ptoken;
        switch ($tokenid) {
          // ignore opening/closing tag
          case T_OPEN_TAG:   $id = NULL; break;
          case T_CLOSE_TAG:  $id = NULL; break;

          // ignore white spaces
          case T_WHITESPACE: $id = NULL; break;

          case T_CONSTANT_ENCAPSED_STRING:
            $id = self::TK_STRING;
            // remove ' or " at the beginning and at the end
            $text = trim($text, $text[0]);
            break;

          case T_STRING:
            $id = self::TK_ID;
            break;

          ///////////////////////////////////////////
          // Add more tokens here!
          // Get a complete list from:
          // http://uk3.php.net/manual/en/tokens.php
          ///////////////////////////////////////////

          default: /** handle error here! */ break;
        }
      }

      // append the token
      if ($id !== NULL) {
        array_push ($tokens, array ($id, $text));
      }
    }

    return $tokens;
  }
}</code></pre>
<p style="text-align: justify;">Básicamente esto es un esqueleto que podría servir para ejemplificar un poco cómo hacer el parser, aunque faltarían muchas cosas que añadir. Luego tokenizar una cadena sería simplemente hacer una llamada a <strong>jtokenizer::tokenize ($string)</strong>.</p>
<p style="text-align: justify;">En el array devuelto por esta nueva función estarán normalizados todos los tokens con nuestros propios identificadores. Por lo que si nos llega un jtokenizer::T_STRING, sabremos que es un string, y en la posición 1 del array estará el propio texto de la cadena. Y lo mismo si nos llega un jtokenizer::T_PLUS.</p>
<p style="text-align: justify;">Creo que con este ejemplo ya es suficiente para que alguien interesado en el tema pueda hacerse el suyo propio, y si no le gusta devolver un array de arrays de 2 elementos, pues puede devolver lo que quiera :p</p>
<p style="text-align: justify;">Para más información, me remito a la documentación de PHP:</p>
<ul style="text-align: justify;">
<li><a href="http://uk3.php.net/token_get_all" target="_blank">Función <strong>token_get_all</strong> en php.net</a></li>
<li><a href="http://uk.php.net/manual/en/book.tokenizer.php" target="_blank">Tokenizador de PHP</a></li>
<li><a href="http://uk3.php.net/manual/en/tokens.php" target="_blank">Lista de tokens devuelta por <strong>token_get_all</strong></a></li>
</ul>
<p style="text-align: justify;"><b>Nota:</b> Si se queire que sea aún más rápido <a href="http://www.codigomanso.com/2008/11/php-switch-vs-array-asociativo/">es mejor usar arrays asociativos en vez de switches</a> <img src='http://www.codigomanso.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.codigomanso.com/es/2008/11/tokenizador-superrapido-en-php/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Un error común en programación</title>
		<link>http://www.codigomanso.com/es/2008/11/un-error-comun-en-programacion/</link>
		<comments>http://www.codigomanso.com/es/2008/11/un-error-comun-en-programacion/#comments</comments>
		<pubDate>Wed, 26 Nov 2008 09:28:16 +0000</pubDate>
		<dc:creator>Pau Sanchez</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programacion]]></category>
		<category><![CDATA[bucles]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[error comun]]></category>

		<guid isPermaLink="false">http://www.codigomanso.com/?p=156</guid>
		<description><![CDATA[Un error que comete mucha gente, aunque mucha no se da cuenta, y la mayoría de veces pasa desapercibido, se da a la hora de poner las condiciones en los bucles. Se debe tener cuidado cuando se hacen llamadas dentro de un bucle, porque algo que a priori puede parecer O(n) se convierte en O(n2).
¿Alguien [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Un error que comete mucha gente, aunque mucha no se da cuenta, y la mayoría de veces pasa desapercibido, se da a la hora de poner las condiciones en los bucles. Se debe tener cuidado cuando se hacen llamadas dentro de un bucle, porque algo que a priori puede parecer O(n) se convierte en O(n<sup>2</sup>).</p>
<p style="text-align: justify;">¿Alguien ve algo raro en el siguiente código?</p>
<pre><code>for ($i = 0; $i &lt; strlen ($string); $i++) {
    // whatever this loop does
}</code></pre>
<p style="text-align: justify;">A priori ¿Parece que todo está bien, no? Si te lo parece es que no eres consciente aún.</p>
<p style="text-align: justify;">Es bien sabido que las condiciones de los bucles se evaluan tantas veces como iteraciones tiene el bucle, con esto no estoy descubriendo nada a nadie, sin embargo, si se mete un <strong>strlen</strong> para medir la longitud de la cadena en un bucle que se ejecuta tantas veces como caracteres hay, acabamos de elevar al cuadrado el tiempo de ejecución.</p>
<p style="text-align: justify;">Tanto en C como en PHP, la función <strong>strlen</strong> necesita recorrer toda la cadena hasta encontrar el &#8216;\0&#8242; para determinar su longitud, así pues, si la longitud es 20, strlen necesitará 20 iteraciones para determinar que la longitud es 20. El problema es que el bucle que estamos haciendo también tiene 20 iteraciones, y en cada iteración se ejecuta strlen, que consume otras 20 iteraciones (claro que en PHP esas 20 iteraciones se ejecutan en código máquina, y no en el interprete), por lo que tendríamos que el coste de ese bucle para una cadena de 20 caracteres es de 20*(20 + lo que hay dentro del bucle) = 400 + 20*lo que hay dentro del bucle.</p>
<p style="text-align: justify;">El siguiente script (<a href="http://www.codigomanso.com/archives/phpscripts/common_mistake_with_loops_using_strlen.php.txt" target="_blank">error común con los bucles</a>) muestra un ejemplo de esto en PHP, donde dentro del bucle no se hace nada, y se puede observar como un bucle es mucho más lento que el otro.</p>
<p style="text-align: justify;">Los resultados tras ejecutarlo en mi ordenador han sido:</p>
<pre><code>strlen($sentence) =  12608 bytes
Making the common mistake: 3.02566313744 seconds
Fixing the common mistake: 0.958508968353 seconds</code></pre>
<p style="text-align: justify;">Creo que se puede apreciar claramente la diferencia <img src='http://www.codigomanso.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p style="text-align: justify;">Finalmente, aunque he usado PHP para ilustrar el error, y concretamente <strong>strlen</strong>, si nos olvidamos de strlen y de PHP, esto es aplicable a otros muchos lenguages C/C++/Java/Pascal/PHP/Python/Perl/Ruby y un largo etcetera; y pasa en todos los lenguajes porque todos los lenguajes usan el mismo concepto, la condicion de salida del bucle se evalua en cada iteración. Quizás no ocurra cuando se utilizan cadenas, porque guardan la longitud en una variable, pero puede que pase al mirar la longitud de listas enlazadas, etc&#8230;</p>
<p style="text-align:justify;"><strong>Conclusión:</strong> si en el bucle estás llamando a una función que siempre te va a devolver lo mismo, mejor guardalo en una variable y usa esa variable dentro del bucle, te ahorrará sorpresas</p>
<p style="text-align:justify;">
<p><strong>Enlaces interesantes:</strong></p>
<ul>
<li><a href="http://www.joelonsoftware.com/articles/fog0000000319.html" target="_blank">Back to basics</a>, un excelente artículo de Joel (<a href="http://local.joelonsoftware.com/mediawiki/index.php/De_vuelta_a_lo_b%C3%A1sico" target="_blank">disponible en Español</a>) donde reflexiona sobre algunas cosas directamente relacionadas con esto.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.codigomanso.com/es/2008/11/un-error-comun-en-programacion/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Como saber si tienes un diccionario o una lista en PHP</title>
		<link>http://www.codigomanso.com/es/2008/11/como-saber-si-tienes-un-diccionario-o-una-lista-en-php/</link>
		<comments>http://www.codigomanso.com/es/2008/11/como-saber-si-tienes-un-diccionario-o-una-lista-en-php/#comments</comments>
		<pubDate>Wed, 19 Nov 2008 13:09:09 +0000</pubDate>
		<dc:creator>Pau Sanchez</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[array]]></category>
		<category><![CDATA[array asociativo]]></category>
		<category><![CDATA[lista]]></category>

		<guid isPermaLink="false">http://www.codigomanso.com/?p=127</guid>
		<description><![CDATA[A veces, en casos muy concretos, es interesante saber si un array es asociativo o es una mera lista de elementos.
La diferencia entre tener un array asociativo (o mapa/diccionario/&#8230;), y una mera lista de elementos, es que no hay claves para acceder a los valores.
Básicamente, la diferencia expresada en código sería:
$asociativo = array ("key1" =&#62; [...]]]></description>
			<content:encoded><![CDATA[<p>A veces, en casos muy concretos, es interesante saber si un array es asociativo o es una mera lista de elementos.</p>
<p>La diferencia entre tener un array asociativo (o mapa/diccionario/&#8230;), y una mera lista de elementos, es que no hay claves para acceder a los valores.</p>
<p>Básicamente, la diferencia expresada en código sería:</p>
<pre><code>$asociativo = array ("key1" =&gt; "value1", "key2" =&gt; "value2", "keyN" =&gt; "valueN");
$lista      = array ("value1", "value2", "valueN");</code></pre>
<p>Aunque uno pueda pensar que es sencillo saber si un array es un diccionario o es una lista, no existe ninguna función en PHP (al menos no la he encontrado), que te de esta información. Y programarlo no es demasiado complicado, pero tampoco se hace en 2 minutos.</p>
<p>A continuación, para el que le interese, pongo las funciones <strong>is_list</strong> y <strong>is_dict</strong> que básicamente nos dicen si un array es una lista o un diccionario (con sólo una llamada podremos diferenciarlos):</p>
<pre><code>function is_list ($array)
{
    if (!is_array ($array))
      return false;

    $keys = array_keys ($array);
    foreach ($keys as $key) {
        if (!is_numeric ($key))
            return false;
    }
    return true;
}

function is_dict ($array) {
    return is_array ($array) &amp;&amp; !is_list ($array);
}</code></pre>
<p>Y como ejemplo, tras ejecutar el siguiente código:</p>
<pre><code>echo "asociativo: " . (is_dict ($asociativo) ? "DICCIONARIO!" : "No diccionario...");
echo "lista: " . (is_dict ($lista) ? "DICCIONARIO!" : "No diccionario...");
echo "\n";
echo "asociativo: " . (is_list ($asociativo) ? "LISTA!" : "No lista...");
echo "lista: " . (is_list ($lista) ? "LISTA!" : "No lista...");</code></pre>
<p>Se obtiene como salida:</p>
<pre><code>asociativo: DICCIONARIO!
lista: No diccionario...

asociativo: No lista...
lista: LISTA!</code></pre>
<p>Que es justo lo que queremos <img src='http://www.codigomanso.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Y aquí, <a href="http://www.codigomanso.com/archives/phpscripts/list_or_dict.php.txt" target="_blank">el enlace con el ejemplo y las funciones para validar en PHP si un array es una lista o un diccionario</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.codigomanso.com/es/2008/11/como-saber-si-tienes-un-diccionario-o-una-lista-en-php/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>
