Si conocen las nuevas capacidades de PHP 5 tal vez hayan oido hablar de la Sobrecarga de Miembros. Esta es particularmente util cuando deseamos crear un almacen de datos. Veamos de que se trata:
class Sobrecarga {
private $properties;
public function __construct() {
$this->properties = array();
}
public function __get($propName) {
print("Accediendo a propiedad "propName<br/>");
return $this->properties[$propName];
}
public function __set($propName, $propValue) {
$this->properties[$propName] = $propValue;
}
}
Lo que tenemos aqui es una clase que define los métodos mágicos __get y __set. Lo que nos permite esto es tener acceso indirecto al hash properties.
$objSobrecarga = new Sobrecarga();
$objSobrecarga->unaPropiedad = 'unValor';
echo $objSobrecarga->unaPropiedad;
Lo que hicimos aqui fue definir una propiedad dinámicamente. Cuando intentamos escribir o leer una propiedad de un objeto Sobrecarga lo que hacemos en realidad es invocar a los métodos __get y __set. Estos métodos acceden al hash properties y escriben (o leen) en el mismo.Ahora, que pasa si tenemos un miembro privado dentro de nuestra clase? Reescribamos la clase y veamos las diferencias:
class Sobrecarga {
private $x;
private $properties;
public function __construct() {
$this->properties = array();
}
public function __get($propName) {
print("Accediendo a propiedad "propName<br/>");
return $this->properties[$propName];
}
public function __set($propName, $propValue) {
print("Escribiendo propiedad "propName<br/>");
$this->properties[$propName] = $propValue;
}
}
$objSobrecarga = new Sobrecarga();
$objSobrecarga->x = 1;
La salida de este script será "Escribiendo la propiedad x". Ahora declaremos x como pública:
class Sobrecarga {
public $x;
private $properties;
public function __construct() {
$this->properties = array();
}
public function __get($propName) {
print("Accediendo a propiedad "propName<br/>");
return $this->properties[$propName];
}
public function __set($propName, $propValue) {
print("Escribiendo propiedad "propName<br/>");
$this->properties[$propName] = $propValue;
}
}
Y corramos el mismo ejemplo:
$objSobrecarga = new Sobrecarga();
$objSobrecarga->x = 1;
El script no mostrará nada. Esto ilustra que el comportamiento de los __get y __set es definido por la visibilidad de un miembro. En el primer ejemplo intentamos acceder a un miembro llamado "x". Como php no encuentra ningún miembro accesible con ese nombre opta por utilizar los __set y __get. Esto lo que hace es crear un valor "x" dentro de properties. En el segundo ejemplo, x es pública por lo tanto es accesible desde fuera de la clase, y por lo tanto, las llamadas a los métodos mágicos son innecesarias. Observen que si declaramos a x como privada y agregamos el get y set correspondiente podemos acceder a ella sin problemas.
class Sobrecarga {
private $x;
private $properties;
public function __construct() {
$this->properties = array();
}
public function __get($propName) {
print("Accediendo a propiedad "propName<br/>");
return $this->properties[$propName];
}
public function __set($propName, $propValue) {
print("Escribiendo propiedad "propName<br/>");
$this->properties[$propName] = $propValue;
}
public function setX($value) {
$this->x = $value
}
public function getX() {
return $this->x;
}
}
Luego...
$objSobrecarga = new Sobrecarga();
$objSobrecarga->setX(1);
Como x es accesible desde dentro de la clase __set nunca es llamada.
Existe una pequeña cuestión con el uso de la sobrecarga de miembros y las referencias. Supongamos que deseamos referenciar a una propiedad de nuestro objeto sobrecarga:
$objSobrecarga = new Sobrecarga();
$objSobrecarga->nombre = 'Mi Objeto';
$nombre = &$objSobrecarga->nombre;
$nombre = 'Pepe';
echo $objSobrecarga->nombre;
El output de este ejemplo será 'Mi Objeto', que podria llegar a no ser el esperado. Esto ocurre porque cuando referenciamos a la propiedad nombre de $objSobrecarga obtenemos el valor, no una referencia. para poder corregir esto hacemos el siguiente cambio:
class Sobrecarga {
private $properties;
public function __construct() {
$this->properties = array();
}
public function &__get($propName) {
return $this->properties[$propName];
}
public function __set($propName, $propValue) {
$this->properties[$propName] = $propValue;
}
}
Ahora podemos obtener referencias a nuestro hash de propiedades sin problema.