<?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; interpretes</title>
	<atom:link href="http://ivanmosquera.net/index.php/tag/interpretes/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>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>
