<?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>ivanmosquera.net &#187; php</title>
	<atom:link href="http://ivanmosquera.net/index.php/tag/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://ivanmosquera.net</link>
	<description> Just another computing weblog</description>
	<lastBuildDate>Mon, 26 Jul 2010 18:54:58 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>es</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Un vistazo a Quercus: PHP by Java</title>
		<link>http://ivanmosquera.net/index.php/2010/05/12/un-vistazo-a-quercus-php-by-java/</link>
		<comments>http://ivanmosquera.net/index.php/2010/05/12/un-vistazo-a-quercus-php-by-java/#comments</comments>
		<pubDate>Wed, 12 May 2010 20:06:10 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[desarrollo]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://ivanmosquera.net/?p=227</guid>
		<description><![CDATA[

Quercus es una implementación de PHP 5.2 escrita totalmente en Java, algo similar al famoso Hiphop de facebook sólo que en lugar de un traductor a C++ se trata de un intérprete PHP que corre en Java.
Se ha oído hablar mucho menos de Quercus que de HipHop pero es probable que Hiphop no llegue a [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><a href="http://ivanmosquera.net/wp-content/uploads/2010/05/appengine-java-php.jpg"><img class="aligncenter size-full wp-image-233" title="appengine-java-php" src="http://ivanmosquera.net/wp-content/uploads/2010/05/appengine-java-php.jpg" alt="" width="358" height="234" /></a></p>
<p style="text-align: center;">
<p>Quercus es una implementación de PHP 5.2 escrita totalmente en Java, algo similar al famoso Hiphop de facebook sólo que en lugar de un traductor a C++ se trata de un intérprete PHP que corre en Java.<br />
Se ha oído hablar mucho menos de Quercus que de HipHop pero es probable que Hiphop no llegue a utilizarse tanto como ya se está utilizando Quercus.<span id="more-227"></span><br />
¿En qué casos puede ser interesante utilizar Quercus?</p>
<ul>
<li>Desplegar aplicaciones web en entornos muy controlados donde sólo se acepta Java o en plataformas cloud computing que no soportan PHP pero sí Java (Google App Engine).</li>
<li>Necesitar cierta mejora en rendimiento que puede suponer utilizar Quercus en ciertas situaciones.</li>
<li>Desplegar scripts PHP encapsulados en una aplicación Java.</li>
<li>Utilizar PHP como motor de scripting de una aplicación Java, desarrollando el frontend por ejemplo en Swing y dejando el trabajo sucio para los scripts PHP.</li>
<li>Integrar aplicaciones PHP desde Java. (Alfresco lo utiliza).</li>
<li>Estás aburrido, probar por curiosidad.</li>
</ul>
<p>Este post se compone de dos partes. En la primera veremos cómo correr un wordpress sobre Quercus y en la segunda introduciré una prueba de concepto de uso de Quercus en el escritorio.</p>
<h3>1. Wordpress sobre Quercus.</h3>
<ul>
<li>Descargamos Resin 3.1, la versión opensource del paquete que incluye Quercus junto a un servidor web.
<pre><code>wget http://www.caucho.com/download/resin-4.0.6.tar.gz</code></pre>
</li>
<li>Descargamos wordpress:
<pre><code>wget http://wordpress.org/latest.zip</code></pre>
</li>
<li>Descomprimimos Resin:
<pre><code>tar xvzf resin-4.0.6.tar.gz</code></pre>
</li>
<li> Ejecutamos resin:
<pre><code>sh resin-4.0.6/bin/resin.sh  start</code></pre>
</li>
<li> Podemos visitar <a href="http://127.0.0.1:8080">http://127.0.0.1:8080/</a></li>
<li>Ahora, sorpresa tratándose de Java <img src='http://ivanmosquera.net/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> , toca editar algo de XML:<br />
Copiamos lo siguiente en un fichero resin-web.xml colocado en webapps/ROOT/WEB-INF/:</li>
</ul>
<pre>&lt;web-app xmlns="http://caucho.com/ns/resin"&gt;
   &lt;servlet-mapping url-pattern="*.php"
                    servlet-class="com.caucho.quercus.servlet.QuercusServlet"&gt;
   &lt;/servlet-mapping&gt;
&lt;/web-app&gt;</pre>
<li>Para probar que está funcionando bien podemos colocar un script con un phpinfo() en webapps/ROOT/.<br />
Veremos que es bastante más feo que el de Zend:</li>
<pre>PHP Version =&gt; 5.2.0
System =&gt; Linux 2.6.31-14-generic i386
Build Date =&gt; 20100413T085542
Configure Command =&gt; n/a
Server API =&gt; CGI
Virtual Directory Support =&gt; disabled
Configuration File (php.ini) Path =&gt; null
PHP API =&gt; 20031224
PHP Extension =&gt; 20041030
Debug Build =&gt; no
Thread Safety =&gt; enabled
Registered PHP Streams =&gt; php, file, http, https</pre>
<li>Colocamos el jar del conector en la carpeta lib de Resin. Para que resin cargue el conector es necesario reiniciarlo:</li>
<li>
<pre><code>sh resin.sh restart</code></pre>
</li>
<p>Ya lo tendremos funcionando, 100% Java, 0% Zend, pero PHP al fin y al cabo, no ha  hecho falta cambiar ni una línea de Wordpress.</p>
<p><strong>2. QuercusFun, prueba de concepto de aplicación Swing y CLI con Quercus.</strong></p>
<p>En github ya existe una prueba de concepto de integrar quercus sin servlet, es decir, como aplicación de escritorio: ( <a href="http://code.google.com/p/phpandallthat/#Detached_Quercus">http://code.google.com/p/phpandallthat/#Detached_Quercus</a> ) pero no es funcional debido a que no autocarga los módulos con lo cual las funciones de php no están disponibles y tampoco cuida otros aspectos como que los scripts no den timeout demasiado pronto. Es decir, en la práctica no funciona.</p>
<p>Mi aportación se llama &#8220;QuercusFun&#8221; y se trata de una aplicación que se puede ejecutar tanto con GUI (Swing) como desde línea de comandos&#8230; y funciona.</p>
<p>A continuación pantallazo y enlaces tanto al repositorio donde he subido el código como a un JAR.</p>
<p><a href="http://ivanmosquera.net/wp-content/uploads/2010/05/quercusfun.png"><img class="alignleft size-full wp-image-239" title="quercusfun" src="http://ivanmosquera.net/wp-content/uploads/2010/05/quercusfun.png" alt="" width="622" height="597" /></a></p>
<h3 style="padding-left: 180px;"><a href="http://ktulur.net/pro/quercusfun/quercusFun.jar">Bajar quercusFun.jar</a></h3>
<p>Para ejecutar como CLI:</p>
<pre><code>java -jar quercusFun.jar fichero.php</code></pre>
<p>y para ejecutar con GUI</p>
<pre><code>java  -jar quercusFun.jar
</code></pre>
<p>Repositorio en GITHUB: <a href="http://github.com/ivmos/QuercusFun">http://github.com/ivmos/QuercusFun</a></p>
]]></content:encoded>
			<wfw:commentRss>http://ivanmosquera.net/index.php/2010/05/12/un-vistazo-a-quercus-php-by-java/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>[Destripando PHP] Las variables</title>
		<link>http://ivanmosquera.net/index.php/2010/04/15/destripando-php-las-variables/</link>
		<comments>http://ivanmosquera.net/index.php/2010/04/15/destripando-php-las-variables/#comments</comments>
		<pubDate>Wed, 14 Apr 2010 23:04:28 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[desarrollo]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[destripando_php]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://ivanmosquera.net/?p=182</guid>
		<description><![CDATA[Con esta entrada comienzo una serie en la que hablaré del lenguaje PHP atendiendo a cómo está implementado internamente, para cada post desarrollaré un pequeño PECL (extensión de PHP) que trabaje los conceptos. En realidad no haría falta recurrir a ese nivel para ver las estructuras internas ya que PHP5 tiene un API de Reflection, [...]]]></description>
			<content:encoded><![CDATA[<p>Con esta entrada comienzo una serie en la que hablaré del lenguaje PHP atendiendo a cómo está implementado internamente, para cada post desarrollaré un pequeño PECL (extensión de PHP) que trabaje los conceptos. En realidad no haría falta recurrir a ese nivel para ver las estructuras internas ya que PHP5 tiene un <a href="http://es.php.net/manual/en/class.reflection.php">API de Reflection</a>, pero sí que es necesario para ver realmente cómo funcionan las cosas.<br />
La motivación de esta serie es ir documentando lo que voy aprendiendo en mi estudio de PHP. En el desarrollo de mi PFC me enganché al tema de los intérpretes y ahora trato de continuar tomando PHP como ejemplo, al mismo tiempo me ayuda a tener una base sólida de cara al <a href="http://www.zend.com/services/certification/php-5-certification/">ZCE</a>.</p>
<p>En este primer post veremos en profundidad cómo se trabajan las variables  en PHP y su idiosincrasia.<br />
<span id="more-182"></span><br />
El PECL que he desarrollado para el mismo se llama &#8220;ejemplovars&#8221; y aporta las siguientes funciones:</p>
<ul>
<li>ejemplovars_print_type($variable)</li>
<li>ejemplovars_print_refcount($variable)</li>
<li>ejemplovars_dump_globalsymtable</li>
<li>ejemplovars_dump_currentsymtable</li>
</ul>
<p>Algunas cosas que veremos ya se trataron en <a href="http://ivanmosquera.net/index.php/2010/02/13/las-referencias-en-php-que-son-y-porque-no-usarlas/">otro post</a> pero he preferido retomar el tema desde el principio.<br />
.</p>
<h3>El zval</h3>
<p>PHP es un lenguaje de tipado débil, esto implica que se realizan un montón de conversiones implícitas entre los tipos de valores hasta el punto que desde el punto de vista del programador PHP puede dar la impresión de que en lugar de haber tipos las cosas funcionan mágicamente. </p>
<p>Los datos en php se almacenan en una estructura de datos llamada &#8220;zval&#8221; (Zend Value). Podemos encontrar esta estructura en &#8220;Zend/Zend.h&#8221;.</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw4">struct</span> _zval_struct <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="coMULTI">/* Variable information */</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; zvalue_value value; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; zend_uint refcount;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; zend_uchar type; &nbsp; &nbsp; &nbsp; </div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; zend_uchar is_ref;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span>;</div>
</li>
</ol>
</div>
<p>Podemos ver que un zval está compuesto por 4 miembros: value, refcount, type y is_ref. refcount es un unsigned integer mientras que type y is_ref son unsigned char.<br />
El miembro &#8220;value&#8221; sin embargo es una estructura union. La diferencia entre un struct y una union es que sólo ocupa lo que necesite el miembro más grande de la union, en lugar de reservarse memoria dedicada a cada uno de los miembros.<br />
Tiene perfecto sentido por tanto que esta estructura de datos sea una union ya que un &#8220;value&#8221; sólo puede ser de un tipo cada vez, usar un struct sería un gran desaprovechamiento.</p>
<h3>Los tipos</h3>
<p>Según la guía de Zend los tipos de datos en PHP son:</p>
<ul>
<li>boolean</li>
<li>int</li>
<li>float</li>
<li>string</li>
<li>array</li>
<li>object</li>
<li>NULL</li>
<li>resource</li>
</ul>
<p>Sin embargo, internamente los tipos son los siguientes (constantes numéricas):</p>
<ul>
<li>IS_NULL: se asigna automáticamente a las variables no inicializadas. La asignación se realiza en php con la palabra reservada NULL. Hay que tener en cuenta que NULL no es lo mismo que FALSE ni que cero, desde php lo parece debido a los casting implícitos que realiza.
</li>
<li>IS_BOOL: sólo puede tomar los valores TRUE y FALSE. Cuando se evalúan expresiones como WHILE o IF, lo que se hace es un casting implícito a ese tipo. Es decir, como en NULL, no se trata de que 0 sea lo mismo que FALSE sino que ese es un casting que se realiza automáticamente.
</li>
<li>IS_LONG: los int en php son internamente &#8220;signed long&#8221;, dependiente de la plataforma (en 32bit el rango es menor que en 64bit). Si en un script php una variable int se sale del rango, se convierte automáticamente al tipo que veremos a continuación.
</li>
<li>IS_DOUBLE: para números de coma flotante se utiliza el tipo &#8220;signed double&#8221; del sistema. Esto supone que la precisión no es exacta. Se entiende con este ejemplo :
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?</span> <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="br0">&#40;</span>int<span class="br0">&#41;</span> <span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">0.1</span> + <span class="nu0">0.7</span><span class="br0">&#41;</span> * <span class="nu0">10</span><span class="br0">&#41;</span>; <span class="kw2">?&gt;</span></div>
</li>
</ol>
</div>
<p>Cuando la precisión es una factor crítico se recomienda el uso de BCMath.</p>
</li>
<li>IS_STRING: cadena de caracteres, se reserva un bloque de memoria para acomodar el string en cuestión, guardando en el zval un puntero al mismo. La longitud del string se guarda también en el zval. Esto permite que el string contenga datos binarios ya que un &#8220;\0&#8243; no lo va a truncar dado que se maneja la longitud independientemente. Debido a esta práctica se dice que los string de php son &#8220;binary safe&#8221;. El bloque de memoria reservado es siempre la longitud del string + 1 ya que se añade &#8220;\0&#8243; al final para que el string se pueda trabajar desde cualquier función sin tener que depender de la longitud guardada en el zval.
</li>
<li>IS_ARRAY: un array en php en realidad no cumple con la definición clásica de array, sino que se trata de un mapa ordenado o tabla. Esto hace que muchos programadores que sólo conocen PHP se lleven una gran sorpresa al enfrentarse a otros lenguajes y ver que los arrays son mucho más limitados que en php. Quizá habría sido más afortunado llamar a este tipo collection o map directamente, pero a efectos prácticos es irrelevante. Aclarado esto, un array de php está implementado con una tabla Hash donde la clave (o label) puede ser un índice numérico o un string asociativo y está relacionada con un valor (o data).
<p>Internamente también se sigue esa generalización y se usa el tipo HashTable en lugar de usar arrays o listas enlazadas. Supongo que habrán considerado que la flexibilidad y facilidad de uso que supone compensa con creces  el impacto que pueda tener en cuanto a eficiencia. El tipo HashTable se encuentra definido en :</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw4">typedef</span> <span class="kw4">struct</span> _hashtable <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; uint nTableSize;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; uint nTableMask;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; uint nNumOfElements;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; ulong nNextFreeElement;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; Bucket *pInternalPointer; &nbsp; &nbsp; &nbsp; <span class="coMULTI">/* Used for element traversal */</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; Bucket *pListHead;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; Bucket *pListTail;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; Bucket **arBuckets;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; dtor_func_t pDestructor;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; zend_bool persistent;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">unsigned</span> <span class="kw4">char</span> nApplyCount;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; zend_bool bApplyProtection;</div>
</li>
<li class="li2">
<div class="de2"><span class="co2">#if ZEND_DEBUG</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> inconsistent;</div>
</li>
<li class="li1">
<div class="de1"><span class="co2">#endif</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span> HashTable;</div>
</li>
</ol>
</div>
</li>
<li>IS_OBJECT: Un objeto de php viene a  ser un array (de php) al que se le añaden métodos, modificadores de acceso y constantes. El modelo de objetos cambió radicalmente de PHP4 a PHP5.</li>
<li>IS_RESOURCE: se trata de un tipo especial utilizado para casos como un puntero FILE o una conexión a base de datos.</li>
</ul>
<h3>Probando con nuestro PECL</h3>
<p>Un ejemplo con nuestro PECL:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?php</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$a</span> = <span class="kw2">true</span>;</div>
</li>
<li class="li1">
<div class="de1">ejemplovars_print_type<span class="br0">&#40;</span><span class="re0">$a</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2"><span class="re0">$a</span> = <span class="kw2">new</span> stdClass<span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$a</span>-&gt;<span class="me1">attr</span> = <span class="nu0">25</span>;</div>
</li>
<li class="li1">
<div class="de1">ejemplovars_print_type<span class="br0">&#40;</span><span class="re0">$a</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$a</span> = <span class="nu0">4</span>;</div>
</li>
<li class="li1">
<div class="de1">ejemplovars_print_type<span class="br0">&#40;</span><span class="re0">$a</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2"><span class="re0">$a</span> = <span class="re0">$a</span> * <span class="nu0">1000000000</span>;</div>
</li>
<li class="li1">
<div class="de1">ejemplovars_print_type<span class="br0">&#40;</span><span class="re0">$a</span><span class="br0">&#41;</span>;</div>
</li>
</ol>
</div>
<p>El resultado en una máquina de 32bits será:</p>

<div class="wp-terminal">user@computer:$ <br/>Tipo: IS_BOOL<br/>Tipo : IS_OBJECT<br/>Tipo: IS_LONG<br/>Tipo : IS_DOUBLE<br/></div>

<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?php</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$a</span> = <span class="nu0">5</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$b</span> = &amp;<span class="re0">$a</span>;</div>
</li>
<li class="li2">
<div class="de2"><span class="re0">$c</span> = &amp;<span class="re0">$a</span>;</div>
</li>
<li class="li1">
<div class="de1">ejemplovars_print_refcount<span class="br0">&#40;</span><span class="re0">$a</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">ejemplovars_print_type<span class="br0">&#40;</span><span class="re0">$a</span><span class="br0">&#41;</span>;</div>
</li>
</ol>
</div>
<p>El resultado será:</p>

<div class="wp-terminal">user@computer:$ <br/>Referenciado 4 veces.<br/>Tipo: IS_LONG<br/></div>

<p>El código de las dos funciones de ejemplovars es el siguiente, he evitado utilizar macros para trabajar con el zval para que quede claro el acceso a la estructura. Está probado en PHP 5.2, para 5.3 es probable que sea necesario algún cambio ya que para el nuevo recolector de basura  han tocado el struct zval. La función ejemplovars_print_type usa paso por valor mientras que ejemplovars_print_refcount usa paso por referencia implícito.</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">PHP_FUNCTION<span class="br0">&#40;</span>ejemplovars_print_refcount<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; zval *arg;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>zend_get_parameters<span class="br0">&#40;</span>ZEND_NUM_ARGS<span class="br0">&#40;</span><span class="br0">&#41;</span>, <span class="nu0">1</span>, &amp;arg<span class="br0">&#41;</span> == FAILURE<span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; RETURN_NULL<span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>!arg-&gt;is_ref<span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; php_printf<span class="br0">&#40;</span><span class="st0">&quot;Referenciado %d veces.<span class="es0">\n</span>&quot;</span>, arg-&gt;refcount<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">PHP_FUNCTION<span class="br0">&#40;</span>ejemplovars_print_type<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;zval *arg;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp;<span class="kw1">if</span> <span class="br0">&#40;</span>zend_get_parameters<span class="br0">&#40;</span>ZEND_NUM_ARGS<span class="br0">&#40;</span><span class="br0">&#41;</span>, <span class="nu0">1</span>, &amp;arg<span class="br0">&#41;</span> == FAILURE<span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; php_error_docref<span class="br0">&#40;</span><span class="kw2">NULL</span> TSRMLS_CC, E_WARNING, <span class="st0">&quot;Falta el parámetro.&quot;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; RETURN_NULL<span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="kw1">switch</span> <span class="br0">&#40;</span>arg-&gt;type<span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; <span class="kw1">case</span> IS_NULL:</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;php_printf<span class="br0">&#40;</span><span class="st0">&quot;Tipo: IS_NULL<span class="es0">\n</span>&quot;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw2">break</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">case</span> IS_BOOL:</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;php_printf<span class="br0">&#40;</span><span class="st0">&quot;Tipo: IS_BOOL<span class="es0">\n</span>&quot;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw2">break</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">case</span> IS_LONG:</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;php_printf<span class="br0">&#40;</span><span class="st0">&quot;Tipo: IS_LONG<span class="es0">\n</span>&quot;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw2">break</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">case</span> IS_DOUBLE:</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;php_printf<span class="br0">&#40;</span><span class="st0">&quot;Tipo : IS_DOUBLE<span class="es0">\n</span>&quot;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw2">break</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">case</span> IS_STRING:</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;php_printf<span class="br0">&#40;</span><span class="st0">&quot;Tipo : IS_STRING<span class="es0">\n</span>&quot;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw2">break</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; <span class="kw1">case</span> IS_ARRAY:</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;php_printf<span class="br0">&#40;</span><span class="st0">&quot;Tipo : IS_ARRAY<span class="es0">\n</span>&quot;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw2">break</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">case</span> IS_OBJECT:</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;php_printf<span class="br0">&#40;</span><span class="st0">&quot;Tipo : IS_OBJECT<span class="es0">\n</span>&quot;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw2">break</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">case</span> IS_RESOURCE:</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;php_printf<span class="br0">&#40;</span><span class="st0">&quot;Tipo: IS_RESOURCE<span class="es0">\n</span>&quot;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw2">break</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">default</span>:</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;php_printf<span class="br0">&#40;</span><span class="st0">&quot;Otro tipo<span class="es0">\n</span>&quot;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p><br/></p>
<h3>Las tablas de símbolos</h3>
<p>Una tabla de símbolos es un HashTable con punteros a zvals. Hay una tabla de símbolos global que se crea al comienzo, y que podemos ver desde nuestros scripts php : $GLOBALS.</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?php</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$a</span> = <span class="st0">&quot;lala&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li2">
<div class="de2"><span class="kw2">function</span> prueba<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="re0">$b</span> = <span class="st0">&quot;jaja&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<a href="http://www.php.net/print_r"><span class="kw3">print_r</span></a><span class="br0">&#40;</span><span class="re0">$GLOBALS</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li2">
<div class="de2">prueba<span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
</ol>
</div>
<p><br/><br />
Veremos que la variable $b no figura en esa tabla de símbolos. Esto es así ya que al entrar en nuevos ámbitos locales, ya sea por entrar en una función o en el método de una clase, se crea una nueva tabla de símbolos y se establece esta como la tabla de símbolos activa. Es decir, en cada momento sólo tendremos acceso a dos tablas de símbolos: la global y la del ámbito concreto en que estemos. Al terminar la vida de una función su tabla de símbolos se destruye. Podemos caer en el error de pensar que entonces sólo va a haber dos tablas de símbolo en memoria como mucho, pero repito: se crea una por cada nuevo ámbito. Si desde una función o método llamas a otro, ya tienes otra tabla de símbolos iniciada sólo que la de la función invocadora no está activa. Con este diseño es fácil entender cómo funciona el concepto de visibilidad de variables locales.</p>
<p>La tabla de símbolos global así como el puntero a las demás se guarda en la estructura _zend_executor_globals. A continuación un fragmento, si quieres verla entera la encontrarás en zend_globals.h.</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="coMULTI">/* symbol table cache */</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; HashTable *symtable_cache<span class="br0">&#91;</span>SYMTABLE_CACHE_SIZE<span class="br0">&#93;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; HashTable **symtable_cache_limit;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; HashTable **symtable_cache_ptr;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; zend_op **opline_ptr;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; HashTable *active_symbol_table;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; HashTable symbol_table; &nbsp; &nbsp; &nbsp; &nbsp; <span class="coMULTI">/* main symbol table */</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; HashTable included_files; &nbsp; &nbsp; &nbsp; <span class="coMULTI">/* files already included */</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; jmp_buf *bailout;</div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; int <a href="http://www.php.net/error_reporting"><span class="kw3">error_reporting</span></a>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; int orig_error_reporting;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; int exit_status;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; zend_op_array *active_op_array;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; HashTable *function_table; &nbsp; &nbsp; &nbsp;<span class="coMULTI">/* function symbol table */</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; HashTable *class_table; &nbsp; &nbsp; &nbsp; &nbsp; <span class="coMULTI">/* class table */</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; HashTable *zend_constants; &nbsp; &nbsp; &nbsp;<span class="coMULTI">/* constants table */</span></div>
</li>
</ol>
</div>
<p><br/><br />
Podemos acceder fácilmente a la estructura zend_globals con la macro EG. ejemplovars tiene dos funciones que acceden a la tabla de símbolos global y la activa respectivamente:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">PHP_FUNCTION<span class="br0">&#40;</span>ejemplovars_dump_globalsymtable<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; php_printf<span class="br0">&#40;</span><span class="st0">&quot;Tabla de simbolos global : <span class="es0">\n</span><span class="es0">\n</span>&quot;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; php_ejemplovars_print_var_hash<span class="br0">&#40;</span>&amp;<span class="br0">&#40;</span>EG<span class="br0">&#40;</span>symbol_table<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">PHP_FUNCTION<span class="br0">&#40;</span>ejemplovars_dump_currentsymtable<span class="br0">&#41;</span> </div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span> &nbsp; &nbsp;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; php_printf<span class="br0">&#40;</span><span class="st0">&quot;Tabla de simbolos actualmente activa : <span class="es0">\n</span><span class="es0">\n</span>&quot;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; php_ejemplovars_print_var_hash<span class="br0">&#40;</span>EG<span class="br0">&#40;</span>active_symbol_table<span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p><br/><br />
La tabla de símbolos global se pasa por referencia ya que zend_executor_globals la incluye directamente en lugar de simplemente un puntero a la misma.</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">Tabla de simbolos global : </div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">The value of GLOBALS is: Array</div>
</li>
<li class="li2">
<div class="de2">The value of _ENV is: Array</div>
</li>
<li class="li1">
<div class="de1">The value of HTTP_ENV_VARS is: Array</div>
</li>
<li class="li1">
<div class="de1">The value of argv is: Array</div>
</li>
<li class="li1">
<div class="de1">The value of argc is: <span class="nu0">1</span></div>
</li>
<li class="li1">
<div class="de1">The value of _POST is: Array</div>
</li>
<li class="li2">
<div class="de2">The value of HTTP_POST_VARS is: Array</div>
</li>
<li class="li1">
<div class="de1">The value of _GET is: Array</div>
</li>
<li class="li1">
<div class="de1">The value of HTTP_GET_VARS is: Array</div>
</li>
<li class="li1">
<div class="de1">The value of _COOKIE is: Array</div>
</li>
<li class="li1">
<div class="de1">The value of HTTP_COOKIE_VARS is: Array</div>
</li>
<li class="li2">
<div class="de2">The value of _SERVER is: Array</div>
</li>
<li class="li1">
<div class="de1">The value of HTTP_SERVER_VARS is: Array</div>
</li>
<li class="li1">
<div class="de1">The value of _FILES is: Array</div>
</li>
<li class="li1">
<div class="de1">The value of HTTP_POST_FILES is: Array</div>
</li>
<li class="li1">
<div class="de1">The value of _REQUEST is: Array</div>
</li>
<li class="li2">
<div class="de2">The value of a is: lala</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">Tabla de simbolos actualmente activa : </div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">The value of b is: jaja</div>
</li>
</ol>
</div>
<p><br/><br />
Próximamente subiré &#8220;ejemplovars&#8221; a github o similar. </p>
<p>Si te interesa el tema de PECL recomiendo el libro &#8220;Extending and Embedding PHP&#8221; de Sara Golemon.</p>
]]></content:encoded>
			<wfw:commentRss>http://ivanmosquera.net/index.php/2010/04/15/destripando-php-las-variables/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Doctest en PHP</title>
		<link>http://ivanmosquera.net/index.php/2010/03/18/doctest-en-php/</link>
		<comments>http://ivanmosquera.net/index.php/2010/03/18/doctest-en-php/#comments</comments>
		<pubDate>Thu, 18 Mar 2010 21:03:55 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[desarrollo]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[doctest]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://ivanmosquera.net/?p=137</guid>
		<description><![CDATA[Doctest es un módulo de Python que permite incluir tests en los comentarios (en los llamados docstring para ser exactos). Pues bien, existe una implementación para PHP en PEAR.

Para desarrollos rápidos (o ágiles que se dice últimamente), Doctest representa una buena forma de escribir tests debido a que utilizar otras herramientas típicas como PHPUnit o [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_146" class="wp-caption aligncenter" style="width: 310px"><img title="ykPzBWTSLc70G4FqoIoG.0" src="http://ivanmosquera.net/wp-content/uploads/2010/03/ykPzBWTSLc70G4FqoIoG.0.jpg" alt="dna" width="300" height="225" /><p class="wp-caption-text">Dana prefiere Haskell</p></div>
<p>Doctest es un módulo de Python que permite incluir tests en los comentarios (en los llamados docstring para ser exactos). Pues bien, existe una implementación para PHP en PEAR.<br />
<span id="more-137"></span></p>
<p>Para desarrollos rápidos (o ágiles que se dice últimamente), Doctest representa una buena forma de escribir tests debido a que utilizar otras herramientas típicas como PHPUnit o Simpletest requiere una metodología de primero escribir los tests y luego implementar, que está muy bien pero la curva de aprendizaje no es despreciable y tiene más sentido en proyectos de cierto recorrido. En realidad los doctest no se suelen considerar una alternativa a los tests unitarios sino una opción más centrada en la documentación y más sencilla aunque menos potente.</p>
<p>Instalamos la herramienta vía PEAR:</p>

<div class="wp-terminal">user@computer:$ pear install -f Testing_DocTest<br/></div>

<p>A continuación un ejemplo de un doctest en php.</p>
<p>El doctest se incluye entre unas etiquetas <strong>&lt;code&gt;</strong>. La salida esperada para que el test sea satisfactorio se escribe tras <strong>&#8220;// expects:&#8221;</strong>.</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?php</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">/**</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* &lt;code&gt;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="coMULTI">&nbsp;* mostrarNumeros(3);</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;*</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* // expects:</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* //0</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* //11</span></div>
</li>
<li class="li2">
<div class="de2"><span class="coMULTI">&nbsp;* //222</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* //3333</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* &lt;/code&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* &nbsp;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;**/</span></div>
</li>
<li class="li2">
<div class="de2"><span class="kw2">function</span> mostrarNumeros<span class="br0">&#40;</span><span class="re0">$num</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="kw1">for</span><span class="br0">&#40;</span><span class="re0">$i</span>=<span class="nu0">0</span>;<span class="re0">$i</span>&lt;=<span class="re0">$num</span>;<span class="re0">$i</span>++<span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">for</span><span class="br0">&#40;</span><span class="re0">$j</span>=<span class="nu0">0</span>;<span class="re0">$j</span>&lt;=<span class="re0">$i</span>;<span class="re0">$j</span>++<span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$i</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="st0">&quot;<span class="es0">\n</span>&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>Para ejecutar los tests :</p>

<div class="wp-terminal">user@computer:$ phpdt numeros.php.<br/></div>

<p>Dará como resultado:</p>

<div class="wp-terminal">user@computer:$ Processing /tmp/numeros.php<br/>[PASS]  function mostrarNumeros<br/><br/>Total time    : 0.0253 sec.<br/>Passed tests  : 1<br/>Skipped tests : 0<br/>Failed tests  : 0<br/></div>

<p>El doctest se suele incluir en la misma cabecera de comentario de phpdoc pero lo he omitido para que quede más claro lo necesario estrictamente para Doctest.</p>
<p>Doctest por defecto sólo considerará que el test ha sido satisfactorio si la salida del script es exactamente la misma que la salida que hemos escrito como esperada pero ¿y si queremos un comportamiento algo más flexible ?</p>
<p>Para ello podemos usar flags que alteren el comportamiento:</p>
<ul>
<li>NORMALIZE_WHITESPACE: se ignoran los espacios en blanco.</li>
<li>CASE_INSENSITIVE:  ignorar mayúsculas/minúsculas</li>
<li>SKIP: ignorar el test</li>
<li>ELLIPSIS: permitir utilizar el comodín [...]. Útil para los casos en que parte de la salida es variable</li>
</ul>
<p>A continuación un ejemplo que usa un flag de ELLIPSIS. También sirve para ver que podemos incluir varios tests en la misma cabecera.</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?php</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">/** </span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* &lt;code&gt;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="coMULTI">&nbsp;* // Usamos ELLIPSIS porque hay una parte de la salida que no podemos predecir</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;*</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* // flags: ELLIPSIS</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* echo testString();</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* // expects:</span></div>
</li>
<li class="li2">
<div class="de2"><span class="coMULTI">&nbsp;* // Lo siguiente no se puede predecir [...].</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;*</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* &lt;/code&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;*</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* &lt;code&gt;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="coMULTI">&nbsp;* // Este es el mismo test pero lo hacemos para ver que podemos dividir la salida con \</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;*</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* // flags: ELLIPSIS</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* echo testString();</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* // expects:</span></div>
</li>
<li class="li2">
<div class="de2"><span class="coMULTI">&nbsp;* // Lo siguiente \</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* // no se puede \</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* // predecir [...].</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;*</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* &lt;/code&gt;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="coMULTI">&nbsp;*</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;*/</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">function</span> testString<span class="br0">&#40;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="kw1">return</span> <a href="http://www.php.net/sprintf"><span class="kw3">sprintf</span></a><span class="br0">&#40;</span><span class="st0">&#8216;Lo siguiente no se puede predecir %s&#8217;</span>, <a href="http://www.php.net/microtime"><span class="kw3">microtime</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>Si la salida esperada para un test es demasiado grande podemos utilizar &#8220;expects-file:&#8221; en lugar de &#8220;expects :&#8221;. El ejemplo de mostrarNumeros quedaría así con expects-file:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?php</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">/**</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* &lt;code&gt;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="coMULTI">&nbsp;* mostrarNumeros(3);</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;*</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* // expects-file: mostrarNumeros.txt</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;*</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* &lt;/code&gt;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="coMULTI">&nbsp;* </span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;**/</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">function</span> mostrarNumeros<span class="br0">&#40;</span><span class="re0">$num</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="kw1">for</span><span class="br0">&#40;</span><span class="re0">$i</span>=<span class="nu0">0</span>;<span class="re0">$i</span>&lt;=<span class="re0">$num</span>;<span class="re0">$i</span>++<span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="kw1">for</span><span class="br0">&#40;</span><span class="re0">$j</span>=<span class="nu0">0</span>;<span class="re0">$j</span>&lt;=<span class="re0">$i</span>;<span class="re0">$j</span>++<span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$i</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="st0">&quot;<span class="es0">\n</span>&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>En el fichero mostrarNumeros.txt incluiremos la salida en bruto, es decir, sin comentar.</p>
<p>Existe también la posibilidad de incluir todo el test en un fichero externo:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;* &lt;code&gt;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;* <span class="co1">// test-file: tests/test1.doctest</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;* &lt;/code&gt;</div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
</ol>
</div>
<p>Por último, existe la posibilidad de insertar cierto código a interpretar antes que todo lo demás. Esto es útil para establecer variables de entorno o para simular una petición HTTP.</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">/** &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* This is a file level test.</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;*</span></div>
</li>
<li class="li2">
<div class="de2"><span class="coMULTI">&nbsp;* &lt;code&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* // setup:</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* // $_ENV['OSTYPE'] = &#8216;linux&#8217;;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* echo OS_TYPE;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* // expects:</span></div>
</li>
<li class="li2">
<div class="de2"><span class="coMULTI">&nbsp;* // linux</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* &lt;/code&gt;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;*/</span></div>
</li>
<li class="li1">
<div class="de1"><a href="http://www.php.net/define"><span class="kw3">define</span></a><span class="br0">&#40;</span><span class="st0">&#8216;OS_TYPE&#8217;</span>, <span class="re0">$_ENV</span><span class="br0">&#91;</span><span class="st0">&#8216;OSTYPE&#8217;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
</ol>
</div>
<p>Como conclusión, los doctest son una pequeña joya de Python que por suerte ha sido portada también a PHP. Permite incrustar los pequeños scripts que probablemente ya haces para probar tus clases y te obliga a ver tus clases desde el punto de vista del usuario de las mismas, de modo que te ayudará a pensar en si la encapsulación es correcta, en si tiene demasiadas dependencias, en si hace demasiadas cosas etc.. Sirve como complemento a los tests unitarios pero también como iniciación a la escritura de tests.</p>
<p>Se suele decir que el código fácil de testear es propio de un software bien diseñado.</p>
<p>Enlaces:</p>
<p><a href="http://code.google.com/p/testing-doctest/">http://code.google.com/p/testing-doctest/</a><br />
<a href="http://pear.php.net/package/Testing_DocTest">http://pear.php.net/package/Testing_DocTest</a><br />
<a href="http://en.wikipedia.org/wiki/Doctest">http://en.wikipedia.org/wiki/Doctest</a><br />
Para ver más ejemplos de uso, lo mejor es ver el fichero de pruebas de Testing-DocTest, disponible en el repositorio:<br />
<a href="http://svn.php.net/repository/pear/packages/Testing_DocTest/trunk/tests/test1.php">http://svn.php.net/repository/pear/packages/Testing_DocTest/trunk/tests/test1.php</a></p>
]]></content:encoded>
			<wfw:commentRss>http://ivanmosquera.net/index.php/2010/03/18/doctest-en-php/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Las referencias en PHP: qué son y el porqué de no usarlas</title>
		<link>http://ivanmosquera.net/index.php/2010/02/13/las-referencias-en-php-que-son-y-porque-no-usarlas/</link>
		<comments>http://ivanmosquera.net/index.php/2010/02/13/las-referencias-en-php-que-son-y-porque-no-usarlas/#comments</comments>
		<pubDate>Sat, 13 Feb 2010 17:17:45 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[software]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[interpretes]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://ivanmosquera.net/?p=101</guid>
		<description><![CDATA[Según un estudio reciente, PHP es actualmente el tercer lenguaje de programación más popular.  Puede sorprender teniendo en cuenta los buenos comentarios que han recibido durante años lenguajes como Ruby y que se daba por seguro el retroceso de PHP.  Yo creo que esto es debido a que la gente que está detrás de [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_108" class="wp-caption aligncenter" style="width: 434px"><img class="size-full wp-image-108" title="elephant-php" src="http://ivanmosquera.net/wp-content/uploads/2010/02/elephant-php.png" alt="elefante" width="424" height="318" /><p class="wp-caption-text">elefante</p></div>
<p>Según un <a href="http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html">estudio reciente</a>, PHP es actualmente el tercer lenguaje de programación más popular.  Puede sorprender teniendo en cuenta los buenos comentarios que han recibido durante años lenguajes como Ruby y que se daba por seguro el retroceso de PHP.  Yo creo que esto es debido a que la gente que está detrás de PHP ha sabido adaptarse a las nuevas tendencias y responder a tiempo. Dos ejemplos muy significativos:</p>
<ul>
<li>PHP5</li>
<li>Zend Framework (y otros)</li>
</ul>
<p><span id="more-101"></span><br />
La comunidad &#8220;phpera&#8221; lejos de quedarse parada ante el adelantamiento por la derecha que parecía que les iba a hacer Ruby/Python/etc han mejorado el lenguaje increíblemente hasta el punto que el diseño OO de PHP tiene poco que envidiar a Java. Me imagino a los desarrolladores allá por el 2003 diciéndo <em>&#8220;Dicen que PHP4 no es enterprise-ready, que su OO da asco, vale, tienen razón.&#8221;</em>. Y de ahí salió PHP5, miras la lista de cambios entre PHP4 y PHP5, y resulta increíble que sólo les separe un número de versión.  Algo parecido se puede decir de &#8220;Zend Framework&#8221;: <em>&#8220;Ruby on Rails mola mucho, un killer app, hagamos algo parecido&#8221;</em>. Y acabó surgiendo Zend Framework, un excelente framework MVC con &#8220;total&#8221; cobertura de test unitarios y completamente modular. Además, surgieron muchos otros framework que rivalizan con ZF, el &#8220;oficial&#8221;, creando una competencia absolutamente sana. Se trata de ejemplos como CakePHP, Symfony o CodeIgniter. El último episodio donde se ha demostrado este pragmatismo de los phperos ha sido dejar Zend_Entity y pasar a adoptar el ORM supuestamente de la competencia : Doctrine. Esto contrasta con la gente de Perl que ha dedicado la mayor parte de sus esfuerzos a crear una máquina virtual, académicamente muy interesante pero en la práctica ¿Hay nuevos usuarios de Perl existiendo PHP, Python y Ruby?.</p>
<p>Vale, a estas alturas te estarás preguntando a qué viene el título de esta entrada. Pues bien, todo esto de la actitud pragmática, los grandes avances etc. está muy bien pero existe un problema en PHP si bien en mi opinión es un mal menor: se trata de mantener la compatibilidad hacia atrás. No sólo un mal menor sino además un mal necesario que permite que los desarrolladores vayan adaptándose a los nuevos cambios progresivamente. La opción contraria podría resultar crítica para muchos usuarios, hay pocos casos donde ha sido necesario ese caso extremo, me viene a la cabeza VisualBasic 6 y poco más.</p>
<p>PHP es un lenguaje que empezó con objetivos mucho más modestos, seguramente <a href="http://es.wikipedia.org/wiki/Rasmus_Lerdorf">Rasmus Lerdof</a> ni en sus sueños más húmedos se imaginó que su herramienta evolucionaría hasta soportar sitios de la escala de Facebook. La política en PHP ha sido ir corrigiendo cosas y manteniendo compatibilidad hacia atrás avisando al desarrollador de las malas prácticas mediante warnings. En esta entrada hablaré de porqué no se debe utilizar a día de hoy referencias en PHP.</p>
<h3>¿Qué son las referencias? &#8220;&amp;&#8221;</h3>
<p>Las referencias de PHP se parecen en esencia a las referencias (que no punteros) de C++. Son algo parecido a los enlaces duros de UNIX. Se han utilizado mucho en PHP debido a que en PHP4 el diseño OO era bastante distinto.  En POO se trabaja con referencias de objetos en lugar de con los datos directamente debido a que la idea es mandar mensajes a los objetos y que ellos mismos sean los encargados de modificar su propio estado, y para eso basta la referencia del objeto para mandarle mensajes, difícilmente vas a necesitar acceder al objeto en sí mismo.<br />
En PHP4, la implementación OO hacía que fuera necesario utilizar el operador referencia para hacer POO ya que de lo contrario estabas copiando objetos.  También hay que tener en cuenta que hasta hace relativamente poco no se programaba OO en PHP por lo que se asumía que al igual que en C, si quieres trabajar con una estructura de datos muy grande, lo suyo es pasarlo por referencia y así evitar la copia. Esto me lleva a explicar un hecho poco conocido de PHP.</p>
<h3>copy-on-write</h3>
<p>La práctica de usar paso por referencia por motivos de optimización es equivocada <em>actualmente </em>debido a que PHP hace copy-on-write. Esto consiste en que PHP cuando se pasa por valor (casi siempre), no hace una copia de la variable desde el principio sino que trabajará en realidad con la referencia y hará una copia sólo en el momento en que detecte que vas a intentar modificar. Es decir, tú como programador feliz, estás en el ámbito de la función y con un parámetro por valor, y parece que estás trabajando desde el principio con una copia con lo cual si la estructura de datos es muy grande te puedes ver tentado a pasar por referencia pero es un error debido a que PHP internamente no hace la copia hasta que sea realmente necesario. Vale, pero puedes estar pensando: ¡ pero es que precisamente mi función va a modificar esa estructura y mucho así que se va a hacer esa costosa copia! Bien, el problema subyacente es que no se está pensando suficientemente a lo OO sino más bien proceduralmente.  En PHP5 el modelo de objetos está rediseñado de modo que los objetos se trabajan con referencias como en Java, por lo que deja de ser necesario utilizar el operador referencia para hacer POO. Esto supone que el operador &#8216;=&#8217; en la práctica es como si copiara sólo para los tipos primitivos mientras que para los objetos copia la referencia. Esta suele ser la típica explicación pero en realidad es errónea, lo cierto es que esta misma mala explicación también se suele dar en Java como simplificación. Lo que ocurre en realidad es que en PHP5 no trabajas con el objeto directamente, trabajas con su referencia, de modo que cuando pasas el objeto por valor, como mucho estarás provocando (copy-on-write) la copia de la referencia pero no del objeto. Si quieres una copia física del objeto lo que necesitarás es clonar el objeto (clone). Puedes utilizar el operador de referencia con objetos también pero resulta innecesario.</p>
<p>Vamos a ver más en profundidad cómo trabaja el intérprete de PHP las variables.</p>

<div class="wp-terminal">user@computer:$ apt-get source php5-cli.<br/></div>

<p>La estructura de datos que almacena una variable en PHP se llama &#8220;zval_struct&#8221; (zval entre amigos).  Un &#8220;zval&#8221; tiene los siguientes campos:</p>
<ul>
<li>tipo (el tipo de la variable)</li>
<li>valor (el valor de la variable)</li>
<li>is_ref (flag que indica si la variable es una referencia &amp;)</li>
<li>refcount (contador del número de símbolos que apuntan a este zval)</li>
</ul>
<p>La estructura está definida en zend.h:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw4">struct</span> _zval_struct <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">/* Variable information */</span></div>
</li>
<li class="li1">
<div class="de1">zvalue_value value; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="coMULTI">/* value */</span></div>
</li>
<li class="li1">
<div class="de1">zend_uint refcount;</div>
</li>
<li class="li2">
<div class="de2">zend_uchar type; &nbsp; &nbsp; &nbsp; &nbsp;<span class="coMULTI">/* active type */</span></div>
</li>
<li class="li1">
<div class="de1">zend_uchar is_ref;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span>;</div>
</li>
</ol>
</div>
<p>Un zvalue_value puede ser muchas cosas. Ahí reside la magia del tipado de php. Tenemos en la misma estructura de datos las distintas posibilidades, tanto tipos primitivos como objetos, en <a href="http://ivanmosquera.net/index.php/2009/10/02/ikuspro-en-beta/">Ikuspro</a> realicé una implementación similar sólo que la genericidad de Java facilita mucho las cosas. Los objetos no se almacenan en esta estructura sino que únicamente se guarda el puntero (en PHP-5).</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw4">typedef</span> <span class="kw4">union</span> _zvalue_value <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">long</span> lval; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="coMULTI">/* long value */</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">double</span> dval; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="coMULTI">/* double value */</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">struct</span> <span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">char</span> *val;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> len;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> str;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; HashTable *ht; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="coMULTI">/* hash table value */</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; zend_object_value obj;</div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#125;</span> zvalue_value;</div>
</li>
</ol>
</div>
<p>En PHP4 probablemente el diseño era distinto de manera que en el valor iba directamente el objeto de manera que era necesario usar continuamente el operador referencia para hacer programación orientada a objetos correctamente.</p>
<p>Un zend_object_value es lo siguiente (zend_types.h):</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw4">typedef</span> <span class="kw4">struct</span> _zend_object_value <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; zend_object_handle handle;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; zend_object_handlers *handlers;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span> zend_object_value;</div>
</li>
</ol>
</div>
<p>El handle es un ID único de entre ese tipo concreto de objetos (no global). El tipo del objeto y su funcionalidad está en esta otra estructura que es encuentra en una tabla. Desde zend_object_value vemos que se apunta con handlers en la entrada adecuada.</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw4">typedef</span> <span class="kw4">struct</span> _zend_object_handlers <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; zend_object_add_ref_t &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;add_ref;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; zend_object_del_ref_t &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;del_ref;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; zend_object_delete_obj_t &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; delete_obj;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; zend_object_clone_obj_t &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;clone_obj;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; zend_object_read_property_t &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;read_property;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; zend_object_write_property_ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;write_property;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; zend_object_get_property_ptr_t &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; get_property_ptr;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; zend_object_get_property_zval_ptr_t &nbsp; &nbsp; &nbsp;get_property_zval_ptr;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; zend_object_get_t &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;get;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; zend_object_set_t &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;set;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; zend_object_has_property_t &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; has_property;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; zend_object_unset_property_t &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; unset_property;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; zend_object_get_properties_t &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; get_properties;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; zend_object_get_method_t &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; get_method;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; zend_object_call_method_t &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;call_method;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; zend_object_get_constructor_t &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;get_constructor;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; zend_object_get_class_entry_t &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;get_class_entry;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; zend_object_get_class_name_t &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; get_class_name;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; zend_object_compare_t &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;compare_objects;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span> zend_object_handlers;</div>
</li>
</ol>
</div>
<p>Los símbolos (nombres de variables) que apuntan a un zval se guardan en una tabla de símbolos. Normalmente solemos hablar de variables locales, variables globales, ámbitos de variables&#8230; Bien, de lo que se trata es que tenemos una tabla de símbolos por ámbito y en PHP el ámbito está unido a las funciones o métodos. En C por ejemplo, es diferente y los ámbitos van unidos a los bloques directamente de modo que tenemos tablas de símbolos por bloques.  Por ejemplo en PHP tenemos:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$a</span> = <span class="st0">&quot;hola/&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1"><a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$a</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$a</span> = <span class="st0">&quot;jaja/&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$a</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$a</span>;</div>
</li>
</ol>
</div>
<p>El resultado será &#8220;hola/jaja/jaja/&#8221;</p>
<p>En C:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="co2">#include </span></div>
</li>
<li class="li1">
<div class="de1">main<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw4">char</span> *a = <span class="st0">&quot;hola/&quot;</span>;</div>
</li>
<li class="li2">
<div class="de2"><a href="http://www.opengroup.org/onlinepubs/009695399/functions/printf.html"><span class="kw3">printf</span></a><span class="br0">&#40;</span><span class="st0">&quot;%s&quot;</span>,a<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw4">char</span> *a = <span class="st0">&quot;jaja/&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1"><a href="http://www.opengroup.org/onlinepubs/009695399/functions/printf.html"><span class="kw3">printf</span></a><span class="br0">&#40;</span><span class="st0">&quot;%s&quot;</span>,a<span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><a href="http://www.opengroup.org/onlinepubs/009695399/functions/printf.html"><span class="kw3">printf</span></a><span class="br0">&#40;</span><span class="st0">&quot;%s&quot;</span>,a<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>El resultado es &#8220;hola/jaja/hola/&#8221;.</p>
<p>Si te parece un detalle de importancia echa un vistazo a este código:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$a</span> = <span class="st0">&quot;Hola&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1"><a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$a</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">if</span> <span class="br0">&#40;</span><span class="re0">$a</span> == <span class="st0">&quot;Hola&quot;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$b</span> = <span class="st0">&quot;Adios&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$b</span>;</div>
</li>
</ol>
</div>
<p>Este código en C no tiene sentido.</p>
<p>Podemos ver los zval con xdebug_debug_zval</p>

<div class="wp-terminal">user@computer:$ apt-get install php5-xdebug<br/></div>

<p>Veamos un ejemplo:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$a</span> = <span class="st0">&quot;Hola&quot;</span>;</div>
</li>
<li class="li2">
<div class="de2">xdebug_debug_zval<span class="br0">&#40;</span><span class="st0">&#8216;a&#8217;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$b</span> = <span class="nu0">2</span>;</div>
</li>
<li class="li1">
<div class="de1">xdebug_debug_zval<span class="br0">&#40;</span><span class="st0">&#8216;b&#8217;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$obj</span> = <span class="kw2">new</span> stdClass<span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$obj</span>-&gt;<span class="me1">atrib1</span> = <span class="st0">&quot;foo&quot;</span>;</div>
</li>
<li class="li2">
<div class="de2"><span class="re0">$obj</span>-&gt;<span class="me1">atrib2</span> = <span class="st0">&quot;bar&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1">xdebug_debug_zval<span class="br0">&#40;</span><span class="st0">&#8216;obj&#8217;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$obj2</span> = <span class="re0">$obj</span>;</div>
</li>
<li class="li1">
<div class="de1">xdebug_debug_zval<span class="br0">&#40;</span><span class="st0">&#8216;obj2&#8242;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$obj3</span> = &amp;<span class="re0">$obj</span>;</div>
</li>
<li class="li2">
<div class="de2">xdebug_debug_zval<span class="br0">&#40;</span><span class="st0">&#8216;obj3&#8242;</span><span class="br0">&#41;</span>;</div>
</li>
</ol>
</div>
<p>El resultado es:</p>
<pre>a: (refcount=1, is_ref=0)='Hola'
b: (refcount=1, is_ref=0)=2
obj: (refcount=1, is_ref=0)=class stdClass { public $atrib1 = (refcount=1, is_ref=0)='foo'; public $atrib2 = (refcount=1, is_ref=0)='bar' }
obj2: (refcount=2, is_ref=0)=class stdClass { public $atrib1 = (refcount=1, is_ref=0)='foo'; public $atrib2 = (refcount=1, is_ref=0)='bar' }
obj3: (refcount=2, is_ref=1)=class stdClass { public $atrib1 = (refcount=1, is_ref=0)='foo'; public $atrib2 = (refcount=1, is_ref=0)='bar' }</pre>
<p>Como puedes ver el único con is_ref=1 es la variable referencia. Un zval se elmina cuando refcount pasa a ser cero y esas referencias van desaparenciendo a medida que se van resolviendo los ámbitos. Es decir, si hemos creado un zval dentro de una función (localmente) tendremos en principio símbolos pertenecientes a la tabla de símbolos de esa función. Al terminar la función ese zval pasará a tener 0 de refcount y por tanto se podrá liberar. Se suele decir que la función unset() de php destruye objetos pero creo que eso no es cierto.  Un ejempo:</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="re0">$orig</span> = <span class="nu0">4</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$a</span> = <span class="re0">$orig</span>;</div>
</li>
<li class="li1">
<div class="de1">xdebug_debug_zval<span class="br0">&#40;</span><span class="st0">&#8216;a&#8217;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2"><span class="re0">$b</span> = &amp;amp;<span class="re0">$a</span>;</div>
</li>
<li class="li1">
<div class="de1">xdebug_debug_zval<span class="br0">&#40;</span><span class="st0">&#8216;a&#8217;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><a href="http://www.php.net/unset"><span class="kw3">unset</span></a><span class="br0">&#40;</span><span class="re0">$a</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">xdebug_debug_zval<span class="br0">&#40;</span><span class="st0">&#8216;b&#8217;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$b</span> .<span class="st0">&quot;<span class="es0">\n</span>&quot;</span>;</div>
</li>
<li class="li2">
<div class="de2"><span class="re0">$obj</span> = <span class="kw2">new</span> stdClass;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$obj</span>-&gt;<span class="me1">foo</span> = <span class="st0">&quot;bar&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$obj2</span> = &amp;amp;<span class="re0">$obj</span>;</div>
</li>
<li class="li1">
<div class="de1">xdebug_debug_zval<span class="br0">&#40;</span><span class="st0">&#8216;obj&#8217;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><a href="http://www.php.net/unset"><span class="kw3">unset</span></a><span class="br0">&#40;</span><span class="re0">$obj</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">xdebug_debug_zval<span class="br0">&#40;</span><span class="st0">&#8216;obj2&#8242;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><a href="http://www.php.net/echo"><span class="kw3">echo</span></a> <span class="re0">$obj2</span>-&gt;<span class="me1">foo</span> .<span class="st0">&quot;<span class="es0">\n</span>&quot;</span>;</div>
</li>
</ol>
</div>
<p>El resultado es:</p>
<pre>a: (refcount=2, is_ref=0)=4
a: (refcount=2, is_ref=1)=4
b: (refcount=1, is_ref=0)=4
4
obj: (refcount=2, is_ref=1)=class stdClass { public $foo = (refcount=1, is_ref=0)='bar' }
obj2: (refcount=1, is_ref=0)=class stdClass { public $foo = (refcount=1, is_ref=0)='bar' }
bar</pre>
<p>Como podemos ver lo que hace unset en realidad es disminuir el número del contador.  Por último un ejemplo en el que pasamos la referencia de un objeto con lo cual hacemos que deje de apuntar a un objeto y pase a ser un string (tipo primitivo):</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">function</span> lafuncion<span class="br0">&#40;</span>stdClass &amp;<span class="re0">$obj</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$obj</span> = <span class="st0">&quot;Sorpresa&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$a</span> = <span class="kw2">new</span> stdClass<span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$a</span>-&gt;<span class="me1">foo</span> = <span class="st0">&quot;bar&quot;</span>;</div>
</li>
<li class="li2">
<div class="de2">xdebug_debug_zval<span class="br0">&#40;</span><span class="st0">&#8216;a&#8217;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">lafuncion<span class="br0">&#40;</span>&amp;<span class="re0">$a</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">xdebug_debug_zval<span class="br0">&#40;</span><span class="st0">&#8216;a&#8217;</span><span class="br0">&#41;</span>;</div>
</li>
</ol>
</div>
<p>El resultado es:</p>
<pre>
a: (refcount=1, is_ref=0)=class stdClass { public $foo = (refcount=1, is_ref=0)='bar' }
a: (refcount=1, is_ref=0)='Sorpresa'</pre>
<p>Como conclusión: no merece la pena trabajar con el operador referencia si estamos haciendo POO, lo único que vamos a conseguir es liar el código y provocar bugs, los punteros y referencias no están al nivel de abstracción que solemos manejar en nuestra vida diaria mientras que los objetos, atributos y métodos sí. Desgraciadamente existe mucho código &#8220;legacy&#8221; que hace uso intensivo de pasos por referencia, incluyendo algunas funciones de ordenación de PHP. Una opción para convertir esas funciones es sustituir los parámetros por referencia por un objeto stdClass que los encapsule pasado por valor.</p>
<p>Links:</p>
<p>Para escribir este post me he basado en el código citado del intérprete de PHP y en los siguientes enlaces. Si crees que he cometido algún error pon un comentario, estaré encantado en aprender:</p>
<p>http://php.net/manual/en/features.gc.refcounting-basics.php</p>
<p>http://schlueters.de/blog/archives/125-Do-not-use-PHP-references.html</p>
<p>http://blog.libssh2.org/index.php?/archives/51-Youre-being-lied-to..html</pre>
]]></content:encoded>
			<wfw:commentRss>http://ivanmosquera.net/index.php/2010/02/13/las-referencias-en-php-que-son-y-porque-no-usarlas/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>
