Renvoie une chaîne en majuscules
Une méthode magique est une méthode événementielle c'est-à-dire qu’elle sera exécutée si un
événement est déclenché, si non rien ne se passe.
Une méthode magique est une méthode événementielle c'est-à-dire qu’elle sera exécutée si un événement est déclenché, si non rien ne se passe.
Nous avons déjà vu une méthode magique dans un chapitre précédent, il s’agit de la méthode
__construct et oui c’est une méthode magique qui est déclanchée pas l’événement instanciation d’une classe (création d’objet).
Si vous voyez une fonction qui commence par un double souligné ( __ ) et bien c’est une méthode magique.
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.
Les méthodes magiques documentées de PHP sont :
__construct | __destruct |
__call | __callStatic |
__get | __set |
__isset | __unset |
__sleep | __wakeup |
__toString | __invoke |
__set_state |
Vous ne pouvez pas utiliser ces noms de méthode dans vos classes, sauf si vous voulez implémenter le comportement associé à ces méthodes magiques.
Cette méthode est déclenchée quand un objet est né par l’appel du mot clé « new », c'est-à-dire à sa création.
Cette méthode est déclenchée quand l’objet est mort c'est-à-dire lorsque la variable qui le contient n'existe plus ou à la fin du script
Le constructeur et le destructeur sont les deux méthodes magiques les plus connues. Ce sont des méthodes (fonctions dans la classe) qui sont appelées automatiquement quand on crée un objet et quand on le "tue".
Voici un exemple que vous pouvez tester pour comprendre le rôle du constructeur et du destructeur.
Exemple :
Exemple : Copier le code
<?php class MaClass { // Constructeur de la classe public function __construct() { echo "Appel du constructeur !\n"; } // Destructeur de la classe public function __destruct() { echo "Appel du destructeur !\n"; } } echo "<pre>"; // La création d'un objet appelle le constructeur. echo "Création d'un objet\n"; $MaClass = new MaClass(); // La destruction de l'objet est implicite à la fin du script echo "Fin du script\n"; echo "</pre>"; ?>
Si un attribut est appelé mais n'existe pas ou on n’a pas l’autorisation d’accès à cet attribut, on appelle cet événement la surcharge d’attribut.
On peut "attraper" l'appel de cet attribut manquant avec une méthode magique.
Les méthodes magiques spéciales __set() et __get() seront déclanchées par cette surcharge.
Lors de l’appel d’un attribut qui n’existe pas ou dont on n’a pas l’autorisation d’accès :
__set() est automatiquement sollicitée s’il s’agit d’une affectation de valeur
et __get() s’il s’agit de demander une valeur.
Cette méthode prend deux paramètres : le premier est le nom de l'attribut auquel on a tenté d'assigner une valeur, le second paramètre est la valeur que l'on a tenté d'assigner à l'attribut. Cette méthode ne retourne rien. Vous pouvez faire ce que vous voulez.
Exemple :
Exemple : Copier le code
<?php class MaClasse { private $AttributPrive; public function __set ($nom, $valeur) { echo "Pas possible d'assigner à l'attribut <strong>", $nom, "</strong> la valeur <strong>", $valeur, "</strong>!<br />"; } } $obj = new MaClasse; $obj->attribut = 'Test attribut inéxistant'; $obj->AttributPrive = 'Test attribut privé'; ?>
Le principe est le même que __set()
Cette méthode prend un paramètre : le nom de l'attribut auquel on a essayé d'accéder
Exemple
Exemple : Copier le code
<?php class MaClasse { private $AttributPrive; public function __get ($nom) { return "Impossible d'accéder à l'attribut <strong>" . $nom . "!</strong><br />"; } } $obj = new MaClasse; echo $obj->attribut; echo $obj->AttributPrive; ?>
La méthode __isset ( $name ) est sollicitée lorsque la fonction isset() ou la fonction empty() sont appelées avec des propriétés inaccessibles.
La méthode __unset( $name) est sollicitée lorsque unset() est appelée avec des propriétés inaccessibles.
Exemple
Exemple : Copier le code
<?php class PropertyTest { /** Variable pour les données surchargées. */ private $data = array(); /** La surcharge n'est pas utilisée sur les propriétés déclarées. */ public $declared = 1; /** La surcharge n'est lancée que lorsque l'on accède à la classe depuis l'extérieur. */ 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; } /** Depuis PHP 5.1.0 */ public function __isset($name) { echo "Est-ce que '$name' est défini ?\n"; return isset($this->data[$name]); } /** Depuis PHP 5.1.0 */ public function __unset($name) { echo "Effacement de '$name'\n"; unset($this->data[$name]); } /** Cette méthode n'est pas magique, nécessaire ici que pour l'exemple. */ 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 utlisée...\n"; echo $obj->hidden . "\n"; echo "</pre>"; ?>
Cet exemple va afficher :
Définition de 'a' à la valeur '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 utlisée...
Récupération de 'hidden'
Notice: Propriété non-définie via __get(): hidden dans <chemin du fichier> à la ligne 69 in <chemin du fichier> on line 28
Si des méthodes inaccessibles sont invoqué, c'est-à-dire qu’on fait appel à une méthode qui n'existe pas ou dont on n’a pas l’autorisation d’accès, on parle de surcharge de méthode.
On peut capter cette événement par les méthodes magiques __call() et __callStatic() .
__call( $name , array $arguments ) est lancée lorsque l'on invoque des méthodes inaccessibles dans le contexte de l'objet.
__callStatic( $name , array $arguments ) est lancée lorsque l'on invoque des méthodes inaccessibles dans un contexte statique.
la méthode __callStatic n'est disponible que depuis PHP 5.3 !
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 :
Exemple : Copier le code
<?php class MaClasse { public function __call ($nom, $arguments) { echo 'Impossible d\'appeler la méthode <strong>', $nom, '</strong>, \'elle n\'existe pas ! les arguments qui lui étaient passés sont les suivants : <strong>', implode ($arguments, '</strong>, <strong>'), '</strong>'; } public static function __callStatic ($nom, $arguments) { echo 'Impossible d\'appeler la méthode <strong>', $nom, '</strong> elle est appelée dans un contexte statique alors qu\'elle n\'existe pas ! les arguments qui lui étaient passés sont les suivants : <strong>', implode ($arguments, '</strong>, <strong>'), '</strong><br />'; } } $obj = new MaClasse; $obj->methode ('arg1', 'arg2'); echo '<br />'; MaClasse::methodeStatique ("param1", "param2"); ?>
Quand on utilise la fonction serialize(), elle vérifie si votre classe a la méthode 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 est linéarisé et une alerte de type E_NOTICE est émise.
Note:
Il n'est pas possible pour __sleep de retourner les noms des propriétés privées des classes parentes. Le faire résulte 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 les 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 possède.
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 : Utilisation de sleep() et wakeup()
Exemple : Copier le code
<?php class Connection { protected $link; private $server, $username, $password, $db; public function __construct($server, $username, $password, $db) { $this->server = $server; $this->username = $username; $this->password = $password; $this->db = $db; $this->connect(); } private function connect() { $this->link = mysql_connect($this->server, $this->username, $this->password); mysql_select_db($this->db, $this->link); } public function __sleep() { return array('server', 'username', 'password', 'db'); } public function __wakeup() { $this->connect(); } } ?>
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.
L’événement donc qui déclanche cette méthode est le fait de traiter un objet comme chaîne de caractères
Cette méthode doit retourner une chaine sinon une erreur E_RECOVERABLE_ERROR sera levée.
Exemple :
Exemple : Copier le code
<?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; ?>
Que s’est il passé ?
En passant l’objet $class comme paramètre de la fonction echo, revient à traiter l’objet comme chaîne de caractères
Et sans la méthode magique __toString une erreur fatal sera émise car la fonction echo ne sait pas comme
réagir , et c’est la méthode __toString détermine comment l'objet doit réagir lorsqu'il est traité comme une chaîne de caractères.
Note :
Il est important de noter qu'avant PHP 5.2.0, la méthode __toString n'était appelée que si elle était directement combinée avec echo() ou print().
Depuis PHP 5.2.0, la méthode __toString est appelée dans tous les contextes de chaîne de caractères (e.g. dans printf() avec le modificateur %s) mais pas dans les autres types de contextes (e.g. avec le modificateur %d). Depuis PHP 5.2.0, convertir un objet sans la méthode __toString en chaîne de caractères émettra une E_RECOVERABLE_ERROR.
La méthode __invoke() est appelée lorsque le script tente d'appeler un objet comme une fonction.
Note:
Cette fonctionnalité est disponible depuis PHP 5.3.0.
Exemple avec __invoke()
Exemple : Copier le code
<?php class CallableClass { public function __invoke($x) { var_dump($x); } } $obj = new CallableClass; $obj(5); var_dump(is_callable($obj)); ?>
Cette méthode statique est appelée pour les classes exportées par la fonction var_export() depuis PHP 5.1.0.
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 de __set_state (depuis PHP 5.1.0)
Exemple : Copier le code
<?php class A { public $var1; public $var2; public static function __set_state($an_array) // Depuis PHP 5.1.0 { $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); ?>
Ce qui affiche :
object(A)[2]
public 'var1' => int 5
public 'var2' => string 'foo' (length=3)