Surcharge magique

La surcharge magique en PHP permet de "créer" dynamiquement des propriétés et des méthodes. Ces entités dynamiques sont traitées via des méthodes magiques établies que l'on peut positionner dans une classe pour divers types d'actions.

Les méthodes magiques de surcharge sont appelées lors de l'interaction avec des propriétés ou des méthodes qui n'ont pas été déclarées ou ne sont pas visibles dans le contexte courant. Le reste de cette section utilise les termes de propriétés inaccessibles et de méthodes inaccessibles pour se référer à cette combinaison de déclaration et de visibilité.

Toutes les méthodes magiques de surcharge doivent être définies comme public.

Note:

Aucun des arguments de ces méthodes magiques ne peut être passé par référence.

Note:

L'interprétation PHP de la surcharge est différente de celle de la plupart des langages orientés objet. La surcharge, habituellement, fournit la possibilité d'avoir plusieurs méthodes portant le même nom mais avec une quantité et des types différents d'arguments.

Surcharge de propriétés

public__set(string$name, mixed$value): void
public__get(string$name): mixed
public__isset(string$name): bool
public__unset(string$name): void

__set() est sollicitée lors de l'écriture de données vers des propriétés inaccessibles (protégées ou privées) ou non existante.

__get() est appelée pour lire des données depuis des propriétés inaccessibles (protégées ou privées) ou non existante.

__isset() est sollicitée lorsque isset() ou empty() sont appelées sur des propriétés inaccessibles (protégées ou privées) ou non existante.

__unset() est invoquée lorsque unset() est appelée sur des propriétés inaccessibles (protégées ou privées) ou non existante.

L'argument $name est le nom de la propriété avec laquelle on interagit. L'argument $value de la méthode __set() spécifie la valeur à laquelle la propriété $name devrait être définie.

La surcharge de propriétés ne fonctionne que dans les contextes objets. Ces méthodes magiques ne seront pas lancées en contexte statique. Par conséquent, ces méthodes ne devraient pas être déclarées comme statiques. Un avertissement est levée si une des méthodes magiques est déclarée comme statique.

Note:

La valeur retournée par __set() est ignorée en raison de la façon dont PHP traite l'opérateur d'affectation. De la même façon, __get() n'est jamais appelée lors d'un enchaînement d'affectation, comme ceci :

 $a = $obj->b = 8; 

Note:

PHP n'appellera pas une méthode surchargée à partir de la même méthode surchargée. Cela signifie, par exemple, qu'écrire return $this->foo à l'intérieur de __get() retournera null et lèvera un E_WARNING s'il n'y a pas de propriété foo définie, plutôt que d'appeler __get() une deuxième fois. Toutefois, les méthodes de surcharge peuvent invoquer d'autres méthodes de surcharge de manière implicite (par exemple, __set() déclenchant __get()).

Exemple #1 Exemple de surcharge de propriétés avec les méthodes __get(), __set(), __isset() et __unset()

<?php
class PropertyTest
{

private $data = array();


public $declared = 1;


private $hidden = 2;

public function
__set($name, $value)
{
echo
"Définition de '$name' à la valeur '$value'\n";
$this->data[$name] = $value;
}

public function
__get($name)
{
echo
"Récupération de '$name'\n";
if (
array_key_exists($name, $this->data)) {
return
$this->data[$name];
}

$trace = debug_backtrace();
trigger_error(
'Propriété non-définie via __get() : ' . $name .
' dans ' . $trace[0]['file'] .
' à la ligne ' . $trace[0]['line'],
E_USER_NOTICE);
return
null;
}

public function
__isset($name)
{
echo
"Est-ce que '$name' est défini ?\n";
return isset(
$this->data[$name]);
}

public function
__unset($name)
{
echo
"Effacement de '$name'\n";
unset(
$this->data[$name]);
}


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
"Manipulons maintenant la propriété privée nommée 'hidden' :\n";
echo
"'hidden' est visible depuis la classe, donc __get() n'est pas utilisée...\n";
echo
$obj->getHidden() . "\n";
echo
"'hidden' n'est pas visible en dehors de la classe, donc __get() est utilisée...\n";
echo
$obj->hidden . "\n";
?>

L'exemple ci-dessus va afficher :

 Définition de 'a' à '1' Récupération de 'a' 1 Est-ce que 'a' est défini ? bool(true) Effacement de 'a' Est-ce que 'a' est défini ? bool(false) 1 Manipulons maintenant la propriété privée nommée 'hidden' : 'hidden' est visible depuis la classe, donc __get() n'est pas utilisée... 2 'hidden' n'est pas visible en dehors de la classe, donc __get() est utilisée... Récupération de 'hidden' Notice: Propriété non-définie via __get() : hidden dans <file> à la ligne 64 dans <file> à la ligne 28 

Surcharge de méthodes

public__call(string$name, array$arguments): mixed
public static__callStatic(string$name, array$arguments): mixed

__call() est appelée lorsque l'on invoque des méthodes inaccessibles dans un contexte objet.

__callStatic() est lancée lorsque l'on invoque des méthodes inaccessibles dans un contexte statique.

L'argument $name est le nom de la méthode appelée. L'argument $arguments est un tableau contenant les paramètres passés à la méthode $name.

Exemple #2 Surcharge de méthodes avec __call() et __callStatic()

<?php
class MethodTest
{
public function
__call($name, $arguments)
{
// Note : la valeur de $name est sensible à la casse.
echo "Appel de la méthode '$name' "
. implode(', ', $arguments). "\n";
}

public static function
__callStatic($name, $arguments)
{
// Note : la valeur de $name est sensible à la casse.
echo "Appel de la méthode statique '$name' "
. implode(', ', $arguments). "\n";
}
}

$obj = new MethodTest;
$obj->runTest('dans un contexte objet');

MethodTest::runTest('dans un contexte static');
?>

L'exemple ci-dessus va afficher :

 Appel de la méthode 'runTest' dans un contexte objet Appel de la méthode statique 'runTest' dans un contexte static 
To Top