miércoles, 4 de abril de 2007

REFERENCIAS EN PHP


En php todos los nombres de las variables están enlazados con valores en memoria automáticamente. Una referencia se puede usar para enlazar dos nombres de variables al mismo valor guardado en memoria.
<?php
//Sin referencia
$color = "azul";
$color2 = $color;
$color = "rojo";
echo $color2; //Imprime azul
//Con referencia
$color = "azul";
$color2 = &$color;
$color = "rojo";
echo $color2; //Imprime rojo

?>

Importancia de las Referencias en PHP
Imagínate que en tu sitio tienes un panel de control que puedes cambiarle el estilo a la páginas. Para eso tenemos dos clases (Estilo, Salida). Veamos una representación simple de como trabajarían estas clases:
<?php
class Estilo {
var $color;
var $size;
function Estilo()
{
$this->color = 'white';
$this->size = 'medium';
}
function getColor()
{
return $this->color;
}
function getSize()
{
return $this->size;
}
function setColor($color)
{
$this->color = $color;
}
function setSize($size)
{
$this->size = $size;
}
}

?>


Ahora la clase Salida:
<?php
class Salida {
var $estilo;
var $salida;
// Constructor toma estilo como argumento
function Salida($estilo)
{
$this->estilo = $estilo;
}
function buildSalida()
{
$this->salida = 'Color is ' . $this->estilo->getColor() .
' and size is ' . $this->estilo->getSize();
}
function display()
{
$this->buildOutput();
return $this->salida;
}
}

Como vemos en la clase salida, su constructor tiene un argumento. Este argumento es un objeto de tipo Salida.
Entonces si ponemos en prática estas clases tendríamos algo como esto:

<?php
//Se crea una instancia de la clase Estilo
$estilo = new Estilo();
$salida = new Salida($estilo);
echo $salida->display();
?>

Esto dará como salida:
Color is white and size is medium

Ahora supongamos que queremos cambiar el estilo del panel que estamos creando.
<?php
//Se crea una instancia de la clase Estilo
$estilo = new Estilo();
$salida = new Salida($estilo);
//Modifico el estilo completamente
$estilo->setColor('red');
$estilo->setSize('large');

//Ahora imprimimos
echo $salida->display();
?>

Salida:
Color is white and size medium

Ahora vemos que lo que imprimimos es lo mismo que en el caso anterior, aunque en este ejemplo se haya cambiado el estilo. El problema consiste en que en la clase Salida el mismo resultado que en ejemplo anterior, debido a que a que la clase Salida obtiene una copia del objeto Estilo, y al realizarse los cambios en el objeto Estilo original no son reflejados en el objeto de la clase Salida ya que está trabajando con una copia.
Pero si modificamos la clase Salida para en vez de trabajar con una copia del objeto Estilo, trabajar con el original, o sea, hacemos referencia al objeto real dentro de la clase Salida, veamos:

function Salida(&$estilo){
$this->estilo = &$estilo;
}

Ahora si volvemos a correr el ejemplo anterior tendríamos otra salida debido a que ahora si estamos trabajando con el objeto original de tipo Estilo. La salida sería:

Color is red and size is large

Buenas Prácticas
Es recomendable color el operador de referencia (&) dentro de la definición de la función, debido a que si lo colocamos en la llamada de la función. A este tipo de referencia se le llama call-time pass-by-reference (obj->funcion(&$obj2)). Si en el php.ini tenemos la opción allow_call_time_pass_reference = Off entonces este tipo de referencia nos dará un warning. php.ini trae esta opción en Off por default.

Cuando debemos usar Referencia
Debemos usar referencia en caso de:
- Con variables complejas estilo arreglos y objetos.
No debemos usar referencias cuando:
- Tengamos variables sencillas estilo integers, strings, etc.


Referencia tomada del libro "The PHP Anthology - Volumen 1"