La sobrecarga en PHP ofrece los medios para "crear" dinámicamente propiedades y métodos. Estas entidades dinámicas se procesan por los métodos mágicos que se pueden establecer en una clase para diversas acciones.
Se invoca a los métodos de sobrecarga cuando se interactúa con propiedades o métodos que no se han declarado o que no son visibles en el ámbito activo. A lo largo de esta sección usaremos los términos "propiedades inaccesibles" y "métodos inaccesibles" para referirnos a esta combinación de declaración y visibilidad.
Todos los métodos sobrecargados deben definirse como public.
Nota:
No se puede pasar ninguno de los parámetros de estos métodos mágicos por referencia.
Nota:
La interpretación de PHP de "overloading" es distinta de la mayoría de los lenguajes orientados a objetos. La sobrecarga tradicionalmente ofrece la capacidad de tener múltiples métodos con el mismo nombre, pero con un tipo o un número distinto de parámetros.
Versión | Descripción |
---|---|
5.3.0 | Se añade __callStatic. Se añadieron advertencias para hacer cumplir la visibilidad public e impedir la declaración static. |
5.1.0 | Añadidos los métodos __isset y __unset. |
$name
)$name
)__set() se ejecuta al escribir datos sobre propiedades inaccesibles.
__get() se utiliza para consultar datos a partir de propiedades inaccesibles.
__isset() se lanza al llamar a isset() o a empty() sobre propiedades inaccesibles.
__unset() se invoca cuando se usa unset() sobre propiedades inaccesibles.
El parámetro $name es el nombre de la propiedad con la que se está interactuando. En el método __set() el parámetro $value especifica el valor que se debe asignar a la propiedad $name.
La sobrecarga de propiedades sólo funciona en contextos de objetos. Estos métodos mágicos no se lanzarán en contextos estáticos. Por esa razón, no se deben declarar como estáticos. Desde PHP 5.3.0, se emite un aviso si alguno de los métodos de sobrecarga es declarado como static.
Nota:
Debido a la forma en que PHP procesa el operador de asignación, el valor que devuelve __set() se ignora. Del mismo modo, nunca se llama a __get() al encadenar asignaciones como ésta:
$a = $obj->b = 8;
Nota:
No se puede utilizar una propiedad sobrecargada en ninguna construcción del lenguaje que no sea isset(). Esto significa que si se invoca a empty() en una propiedad sobrecargada, no se llamará al método de sobrecarga.
Para solventar esta limitación, se debe copiar la propiedad sobrecargada en una variable de ámbito local que empty() pueda manejar.
Ejemplo #1 Sobrecarga de propiedades mediante los métodos __get(), __set(), __isset() y __unset()
<?php
class PropertyTest
{
/** Localización de los datos sobrecargados. */
private $data = array();
/** La sobrecarga no se usa en propiedades declaradas. */
public $declared = 1;
/** La sobre carga sólo funciona aquí al acceder desde fuera de la clase. */
private $hidden = 2;
public function __set($name, $value)
{
echo "Estableciendo '$name' a '$value'\n";
$this->data[$name] = $value;
}
public function __get($name)
{
echo "Consultando '$name'\n";
if (array_key_exists($name, $this->data)) {
return $this->data[$name];
}
$trace = debug_backtrace();
trigger_error(
'Propiedad indefinida mediante __get(): ' . $name .
' en ' . $trace[0]['file'] .
' en la línea ' . $trace[0]['line'],
E_USER_NOTICE);
return null;
}
/** Desde PHP 5.1.0 */
public function __isset($name)
{
echo "¿Está definido '$name'?\n";
return isset($this->data[$name]);
}
/** Desde PHP 5.1.0 */
public function __unset($name)
{
echo "Eliminando '$name'\n";
unset($this->data[$name]);
}
/** No es un método mágico, esta aquí para completar el ejemplo. */
public function getHidden()
{
return $this->hidden;
}
}
echo "<pre>\n";
$obj = new PropertyTest;
$obj->a = 1;
echo $obj->a . "\n\n";
var_dump(isset($obj->a));
unset($obj->a);
var_dump(isset($obj->a));
echo "\n";
echo $obj->declared . "\n\n";
echo "Vamos a probar con la propiedad privada que se llama 'hidden':\n";
echo "Las propiedades privadas pueden consultarse en la clase, por lo que no se usa __get()...\n";
echo $obj->getHidden() . "\n";
echo "Las propiedades privadas no son visibles fuera de la clase, por lo que se usa __get()...\n";
echo $obj->hidden . "\n";
?>
El resultado del ejemplo sería:
Estableciendo 'a' a '1' Consultando 'a' 1 ¿Está definido 'a'? bool(true) Eliminando 'a' ¿Está definido 'a'? bool(false) 1 Vamos a probar con la propiedad privada que se llama 'hidden': Las propiedades privadas pueden consultarse en la clase, por lo que no se usa __get()... 2 Las propiedades privadas no son visibles fuera de la clase, por lo que se usa __get()... Consultando 'hidden' Notice: Propiedad indefinida mediante __get(): hidden en <file> en la línea 69 in <file>en la línea 28
__call() es lanzado al invocar un método inaccesible en un contexto de objeto.
__callStatic() es lanzado al invocar un método inaccesible en un contexto estático.
El parámetro $name corresponde al nombre del método al que se está llamando. El parámetro $arguments es un array enumerado que contiene los parámetros que se han pasado al método $name.
Ejemplo #2 Sobrecarga de métodos mediante los métodos __call() and __callStatic()
<?php
class MethodTest
{
public function __call($name, $arguments)
{
// Nota: el valor $name es sensible a mayúsculas.
echo "Llamando al método de objeto '$name' "
. implode(', ', $arguments). "\n";
}
/** Desde PHP 5.3.0 */
public static function __callStatic($name, $arguments)
{
// Nota: el valor $name es sensible a mayúsculas.
echo "Llamando al método estático '$name' "
. implode(', ', $arguments). "\n";
}
}
$obj = new MethodTest;
$obj->runTest('en contexto de objeto');
MethodTest::runTest('en contexto estático'); // Desde PHP 5.3.0
?>
El resultado del ejemplo sería:
Llamando al método de objeto 'runTest' en contexto de objeto Llamando al método estático 'runTest' en contexto estático