Méthodes magiques
Les noms de méthodes
__construct(),
__destruct(),
__call(),
__callStatic(),
__get(),
__set(),
__isset(),
__unset(),
__sleep(),
__wakeup(),
__serialize(),
__unserialize(),
__toString(),
__invoke(),
__set_state()
__clone() et
__debugInfo()
sont magiques dans les classes PHP. Vous ne pouvez pas utiliser ces noms de méthodes
dans vos classes, sauf si vous voulez implémenter
le comportement associé à ces méthodes magiques.
Note:
Toutes les méthodes magiques DOIVENT être déclarées en public
Attention
PHP réserve tous les noms de fonctions commençant par un double souligné
__
pour les méthodes magiques. Il est recommandé de
ne pas utiliser de noms de fonctions commençant par __
sauf si vous voulez des fonctionnalités magiques documentées.
public __sleep
(
) : array
public __wakeup
(
) : void
serialize() vérifie si la classe a une méthode avec le
nom magique __sleep().
Si c'est le cas, cette méthode sera exécutée avant toute linéarisation. Elle peut
nettoyer l'objet, et elle est supposée retourner un tableau avec les noms de toutes
les variables de l'objet qui doivent être linéarisées.
Si la méthode ne retourne rien, alors null
sera linéarisé, et une alerte de type
E_NOTICE
sera émise.
Note:
Il n'est pas possible pour __sleep() de retourner
des noms de propriétés privées des classes parentes. Le faire
résultera en une erreur de niveau E_NOTICE
.
À la place, vous devriez utiliser l'interface Serializable.
Le but avoué de __sleep() est de valider des données en attente
ou d'effectuer des opérations de nettoyage.
De plus, cette fonction est utile si vous avez de très gros objets
qui n'ont pas besoin d'être sauvegardés en totalité.
Réciproquement, la fonction unserialize() vérifie
la présence d'une méthode dont le nom est le nom magique
__wakeup(). Si elle est présente, cette fonction
peut reconstruire toute ressource que l'objet pourrait posséder.
Le but avoué de __wakeup() est de rétablir
toute connexion de base de données qui aurait été perdue
durant la linéarisation et d'effectuer des tâches de réinitialisation.
Exemple #1 Utilisation de sleep() et wakeup()
<?php
class Connection
{
protected $link;
private $dsn, $username, $password;
public function __construct($dsn, $username, $password)
{
$this->dsn = $dsn;
$this->username = $username;
$this->password = $password;
$this->connect();
}
private function connect()
{
$this->link = new PDO($this->dsn, $this->username, $this->password);
}
public function __sleep()
{
return array('dsn', 'username', 'password');
}
public function __wakeup()
{
$this->connect();
}
}
?>
public __serialize
(
) : array
public __unserialize
( array $data
) : void
serialize() vérifie si la classe a une méthode avec le
nom magique __serialize().
Si c'est le cas, cette méthode sera exécutée avant toute linéarisation.
Elle doit construire et retourner un tableau associatif de paire clé/valeur
qui représente la forme linéarisée de l'objet. Si aucun tableau n'est
retournée une TypeError sera lancée.
Note:
Si __serialize() et
__sleep() sont tout les deux définie
dans le même objet, alors seulement __serialize()
sera appelé.
__sleep() sera ignoré. Si l'objet
implémente l'interface Serializable,
la méthode serialize()
de l'interface sera ignorée et
__serialize() sera utilisé à la place.
L'utilisation prévue de __serialize()
est de définir une représentation arbitraire de l'objet pour le linéariser
facilement. Les éléments du tableau peuvent correspondre aux propriétés de
l'objet mais cei n'est pas requis.
inversement, unserialize() vérifie la présence d'une
fonction avec le nom magique
__unserialize().
Si présent, cette fonction sera passé le tableau restauré qui a été retournée
depuis __serialize(). Il peut alors
restaurer les propriétés de l'objet depuis ce tableau comme approprié.
Note:
Si __unserialize() et
__wakeup() sont tout les deux définie
dans le même objet, alors seulement __unserialize()
sera appelée.
__wakeup() sera ignorée.
Note:
Cette fonctionnalité est disponible à partir de PHP 7.4.0.
Exemple #2 Serialize et unserialize
<?php
class Connection
{
protected $link;
private $dsn, $username, $password;
public function __construct($dsn, $username, $password)
{
$this->dsn = $dsn;
$this->username = $username;
$this->password = $password;
$this->connect();
}
private function connect()
{
$this->link = new PDO($this->dsn, $this->username, $this->password);
}
public function __serialize(): array
{
return [
'dsn' => $this->dsn,
'user' => $this->username,
'pass' => $this->password,
];
}
public function __unserialize(array $data): void
{
$this->dsn = $data['dsn'];
$this->username = $data['user'];
$this->password = $data['pass'];
$this->connect();
}
}?>
public __toString
(
) : string
La méthode __toString() détermine comment l'objet
doit réagir lorsqu'il est traité comme une chaîne de caractères.
Par exemple, ce que echo $obj;
affichera. Cette méthode doit
retourner une chaîne, sinon une erreur E_RECOVERABLE_ERROR
sera levée.
Avertissement
Il était impossible de lancer une exception depuis la méthode
__toString() avant PHP 7.4.0.
En faisant ceci une erreur fatale en résultera.
Exemple #3 Exemple simple
<?php
// Déclaration d'une classe simple
class ClasseTest
{
public $foo;
public function __construct($foo)
{
$this->foo = $foo;
}
public function __toString()
{
return $this->foo;
}
}
$class = new ClasseTest('Bonjour');
echo $class;
?>
L'exemple ci-dessus va afficher :
__invoke
(
...$values
) :
mixed
La méthode __invoke() est appelée lorsqu'un script tente
d'appeler un objet comme une fonction.
Exemple #4 Exemple avec __invoke()
<?php
class CallableClass
{
public function __invoke($x)
{
var_dump($x);
}
}
$obj = new CallableClass;
$obj(5);
var_dump(is_callable($obj));
?>
L'exemple ci-dessus va afficher :
static __set_state
( array $properties
) : object
Cette méthode statique est appelée
pour les classes exportées par la fonction var_export().
Le seul paramètre de cette méthode est un tableau contenant les propriétés
exportées sous la forme array('propriété' => valeur, ...)
.
Exemple #5 Utilisation de __set_state()
<?php
class A
{
public $var1;
public $var2;
public static function __set_state($an_array)
{
$obj = new A;
$obj->var1 = $an_array['var1'];
$obj->var2 = $an_array['var2'];
return $obj;
}
}
$a = new A;
$a->var1 = 5;
$a->var2 = 'foo';
eval('$b = ' . var_export($a, true) . ';'); // $b = A::__set_state(array(
// 'var1' => 5,
// 'var2' => 'foo',
// ));
var_dump($b);
?>
L'exemple ci-dessus va afficher :
object(A)#2 (2) {
["var1"]=>
int(5)
["var2"]=>
string(3) "foo"
}
Note:
Lors de l'exportation d'un objet, var_export() ne
vérifie pas si __set_state() est
implémenté par la classe de l'objet, de sorte que la réimportation de ces
objets échouera, si __set_state() n'est pas implémenté. En particulier,
cela affecte certaines classes internes.
Il est de la responsabilité du programmeur de vérifier que seuls les objets dont la classe implémente __set_state() seront ré-importés.
__debugInfo
(
) : array
Cette méthode est appelée par var_dump() lors
du traitement d'un objet pour récupérer les propriétés qui
doivent être affichées. Si la méthode n'est pas définie dans un objet,
alors toutes les propriétés publiques, protégées et privées seront
affichées.
Exemple #6 Utilisation de __debugInfo()
<?php
class C {
private $prop;
public function __construct($val) {
$this->prop = $val;
}
public function __debugInfo() {
return [
'propSquared' => $this->prop ** 2,
];
}
}
var_dump(new C(42));
?>
L'exemple ci-dessus va afficher :
object(C)#1 (1) {
["propSquared"]=>
int(1764)
}