Sobrecarga

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.

Historial de cambios

Versión Descripción
5.3.0 Se añadió __callStatic. Se añadieron advertencias para hacer cumplir la visibilidad pública e impedir la declaración static.
5.1.0 Se añadieron __isset() y __unset(). Se añadió el soporte para __get() para la sobrecarga de propiedades privadas.
5.0.0 Se añadió __get().

Sobrecarga de propiedades

public __set ( string $name , mixed $value ) : void
public __get ( string $name ) : mixed
public __isset ( string $name ) : bool
public __unset ( string $name ) : void

__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 esta:

 $a = $obj->b = 8; 

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->1;
echo 
$obj->"\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

Sobrecarga de métodos

public __call ( string $name , array $arguments ) : mixed
public static __callStatic ( string $name , array $arguments ) : mixed

__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