Las referencias en PHP bien explicadas

Creo que todo el mundo sabe lo que es una variable. Si no lo sabes no te preocupes… pero ahí tienes la puerta.

Bueno, ya que en la sala solo estamos los que sabemos qué es una variable demos un pasito más: las referencias.

¿Qué es una referencia en PHP?

Para entender lo que es una referencia vamos a llamar a Paco. Paco es un imbécil. Le llaman «el imbécil del barrio». Cuando alguien dice «Paco» o «el imbécil del barrio» se están refiriendo a la misma persona.

Un día, de forma inexplicable, alguien decidió clonar a Paco. El clon de paco era igual que paco en todos los aspectos. Pero todos le llaman «el clon de Paco». Cuando alguien se dice «Paco» o «el imbécil del barrio» se siguen refiriendo al Paco original.

A partir de haber clonado a Paco, su clon empezará a ser diferente, puede que incluso acabe siendo menos imbécil que el Paco original. Pero Paco seguirá siendo imbécil. Y puede ser diferente porque, insisto, no es Paco, a pesar de ser una copia de él.

Hacer una copia de una variable en PHP

Con las variables en PHP pasa lo mismo:

$paco = 'Una persona imbécil';
$clonDePaco = $paco;

Aquí tenemos a $paco que es ‘Una persona imbécil’.

Y tenemos a $clonDePaco que es una copia de $paco y, por tanto, ‘Una persona imbécil’.

Ahora vamos a cambiar al clon:

$clonDePaco = 'Una persona un poco menos imbécil';

El clon ha cambiado, pero $paco no:

echo $paco; // Esto seguirá mostrando 'Una persona imbécil'

Crear una referencia en PHP

¿He dicho que $paco es imbécil? Bueno, pues vamos a llamarle «el imbécil del barrio»:

$elImbecilDelBarrio = &$paco;

Esto es lo que se llama una referencia. Si conseguimos mejorar a la persona a la que hace referencia $elImbecilDelBarrio… ¡estaremos mejorando a Paco!

$elImbecilDelBarrio = 'Una persona un poco menos insoportable';
echo $paco; // Ahora sí, esto mostrará 'Una persona un poco menos insoportable'

$this es una referencia

¿A que pensabas que nunca habías usado una referencia? Pues, si han programado orientado a objetos resulta que sí las habías usado porque $this es una referencia al propio objeto.

Los zval de PHP

Aquí nos metemos ya en droga más dura. Resulta que las variables en PHP se guardan en una cosa llamada «contenedor ZVAL«. Este zval contiene la siguiente información:

  • El tipo de variable.
  • El contenido de la variable.
  • Un bit que indica si es una referencia o una variable «normal» (este campo se llama is_ref).
  • Un bit que indica cuántas referencias hay a esta variable (este campo se llama refcount).

Si quieres ver en acción esto del zval puedes usar la función xdebug_debug_zbal (necesitarás el paquete php7.4-xdebug, o el que corresponda a tu versión de PHP):

$paco = 'Un imbécil';
xdebug_debug_zval('paco');
$elImbecilDelBarrio = &$paco;
xdebug_debug_zval('paco');
xdebug_debug_zval('elImbecilDelBarrio');

Esto muestra el siguiente resultado:

paco: (interned, is_ref=0)='Un imbécil'
paco: (refcount=2, is_ref=1)='Un imbécil'
elImbecilDelBarrio: (refcount=2, is_ref=1)='Un imbécil'

Como puedes ver, cuando se crea $paco, ésta es una variable sin referencias is_ref=0. En cuanto creamos una referencia cambia y pasa a ser is_ref=1 y, además, se actualiza el contador de referencias a refcount=2.

Las referencias de PHP no son como los punteros de C

A mí esto me confundió al principio porque yo comencé programando en C. Pero no, las referencias de PHP no son punteros a la memoria. Olvídate de eso.

Conclusión

De todo esto podemos concluir que una referencia es una especie de «alias» de una variable. Distintas formas de llamar a una misma variable.

Y ¿Puede ser un imbécil menos imbécil con ayuda? Ahí ya no me meto.

Me siento solo, dime algo...