Sobrecarga mágica
En esta página
Sobrecarga mágica#
La sobrecarga mágica en PHP permite “crear” dinámicamente propiedades y métodos. Estas entidades dinámicas son tratadas a través de métodos mágicos establecidos que se pueden posicionar en una clase para diversos tipos de acciones.
Los métodos mágicos de sobrecarga son llamados durante la interacción con propiedades o métodos que no han sido declarados o no son visibles en el contexto actual. El resto de esta sección utiliza los términos de “propiedades inaccesibles” y de “métodos inaccesibles” para referirse a esta combinación de declaración y visibilidad.
Todos los métodos mágicos de sobrecarga deben ser definidos como public.
[!NOTE] Ninguno de los argumentos de estos métodos mágicos puede ser pasado por referencia.
[!NOTE] La interpretación PHP de la “sobrecarga” es diferente de la de la mayoría de los lenguajes orientados a objetos. La sobrecarga, habitualmente, proporciona la posibilidad de tener varios métodos con el mismo nombre pero con una cantidad y tipos diferentes de argumentos.
Sobrecarga de propiedades#
public __set(string $name, mixed $value): void
```php
```php
public __get(string $name): mixed
public __isset(string $name): bool
```php
```php
public __unset(string $name): void
__set() es solicitada al escribir datos hacia propiedades inaccesibles (protegidas o privadas) o no existentes.
__get() es llamada para leer datos desde propiedades inaccesibles (protegidas o privadas) o no existentes.
__isset() es solicitada cuando isset o empty son llamadas sobre propiedades inaccesibles (protegidas o privadas) o no existentes.
__unset() es invocada cuando unset es llamada sobre propiedades inaccesibles (protegidas o privadas) o no existentes.
El argumento $name es el nombre de la propiedad con la que se interactúa. El argumento del método __set() $value especifica el valor al que la propiedad $name debería ser definida.
La sobrecarga de propiedades solo funciona en contextos de objeto. Estos métodos mágicos no serán lanzados en contexto estático. Por consiguiente, estos métodos no deberían ser declarados como estáticos. Se lanza un aviso si alguno de los métodos mágicos es declarado como static.
[!NOTE] El valor devuelto por __set() es ignorado debido a la forma en que PHP trata el operador de asignación. De la misma manera, __get() nunca es llamada durante una asignación encadenada, como esta:
$a = $obj->b = 8;[!NOTE] PHP no llamará a un método sobrecargado desde el mismo método sobrecargado. Esto significa, por ejemplo, que escribir
return $this->foodentro de __get() devolveránully lanzará unE_WARNINGsi no hay una propiedadfoodefinida, en lugar de llamar a __get() una segunda vez. Sin embargo, los métodos de sobrecarga pueden invocar otros métodos de sobrecarga de manera implícita (por ejemplo, __set() desencadenando __get()).
Ejemplo de sobrecarga de propiedades con los métodos __get(), __set(), __isset() y __unset()
<?php
class PropertyTest
{
/** Variable para los datos sobrecargados. */
private $data = array();
/** La sobrecarga no es utilizada en las propiedades declaradas. */
public $declared = 1;
/** La sobrecarga solo es lanzada cuando se accede a esta propiedad desde fuera de la clase. */
private $hidden = 2;
public function __set($name, $value)
{
echo "Definición de '$name' al valor '$value'\n";
$this->data[$name] = $value;
}
public function __get($name)
{
echo "Recuperación de '$name'\n";
if (array_key_exists($name, $this->data)) {
return $this->data[$name];
}
$trace = debug_backtrace();
trigger_error(
'Propiedad no definida vía __get() : ' . $name .
' en ' . $trace[0]['file'] .
' en la línea ' . $trace[0]['line'],
E_USER_NOTICE);
return null;
}
public function __isset($name)
{
echo "¿Está '$name' definido?\n";
return isset($this->data[$name]);
}
public function __unset($name)
{
echo "Borrado de '$name'\n";
unset($this->data[$name]);
}
/** Este no es un método mágico, necesario aquí solo para el ejemplo. */
public function getHidden()
{
return $this->hidden;
}
}
$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 "Manipulemos ahora la propiedad privada llamada 'hidden' :\n";
echo "'hidden' es visible desde la clase, por lo que __get() no es utilizado...\n";
echo $obj->getHidden() . "\n";
echo "'hidden' no es visible fuera de la clase, por lo que __get() es utilizado...\n";
echo $obj->hidden . "\n";
?>
El ejemplo anterior mostrará:
Definición de 'a' a '1'
Recuperación de 'a'
1
¿Está 'a' definido?
bool(true)
Borrado de 'a'
¿Está 'a' definido?
bool(false)
1
Manipulemos ahora la propiedad privada llamada 'hidden' :
'hidden' es visible desde la clase, por lo que __get() no es utilizado...
2
'hidden' no es visible fuera de la clase, por lo que __get() es utilizado...
Recuperación de 'hidden'
Notice: Propiedad no definida vía __get() : hidden en <file> en la línea 64 en <file> en la línea 28
Sobrecarga de métodos#
public __call(string $name, array $arguments): mixed
```php
```php
public static __callStatic(string $name, array $arguments): mixed
__call() es llamada cuando se invoca métodos inaccesibles en un contexto de objeto.
__callStatic() es lanzada cuando se invoca métodos inaccesibles en un contexto estático.
El argumento $name es el nombre del método llamado. El argumento $arguments es un array que contiene los parámetros pasados al método $name.
Sobrecarga de métodos con __call() y __callStatic()
<?php
class MethodTest
{
public function __call($name, $arguments)
{
// Nota: el valor de $name es sensible a mayúsculas y minúsculas.
echo "Llamada al método '$name' "
. implode(', ', $arguments). "\n";
}
public static function __callStatic($name, $arguments)
{
// Nota: el valor de $name es sensible a mayúsculas y minúsculas.
echo "Llamada al método estático '$name' "
. implode(', ', $arguments). "\n";
}
}
$obj = new MethodTest;
$obj->runTest('en un contexto de objeto');
MethodTest::runTest('en un contexto static');
?>
El ejemplo anterior mostrará:
Llamada al método 'runTest' en un contexto de objeto
Llamada al método estático 'runTest' en un contexto static