ex0ns

about
A Computer Science Student's blog, about programming, algorithms, hack and a lot more.

La surcharge magique en PHP (__set et __get)

07 Jul 2012

Cette surcharge est détaillée dans la documentation de PHP. Comme vous le savez peut être, les attributs d’une classe en PHP ne sont accessibles (par défaut) que depuis l’intérieur de cette classe, et pour les récupérer depuis l’extérieur, il faut créer des setters et getters, cela nécessite l'écriture de fonction répétitives et une augmentation importante de la taille de vos classes (tous les getters et setters se ressemblent). Grâce à la surcharge magique, nous allons pouvoir écrire une seule méthode qui permettra de récupérer tous les attributs de la classe facilement (cela comporte cependant de nombreux risques).

Dans notre classe, il faut d’abord déclarer un tableau (privé) qui contiendra tous les attributs de la classe

private $public_attributes = array();

Attaquons nous maintenant à la création de l’objet, grâce à la méthode __construct() qui fait également parti des surcharges magiques (on remarque le __ devant la méthode).

public function __construct(){
    $this->public_attributes[‘nom’] = "ex0ns" ;
    $this->public_attributes[‘site’] = "https://ex0ns.me" ;
}

Ainsi, lorsque que l’on créer un nouvel objet, il aura deux attributs, « nom » et « site » qui seront par défaut initialisés. Voyons maintenant ce que donne l’implémentation de la méthode __get($value) dans cette classe.

public fonction __get($value){
    if(array_key_exists($value, $this->public_attributes)){
       return $this->public_attributes[$value];
        }
}

Ainsi, c’est cette méthode qui sera appelée lorsque vous tenterez d’accéder à un attribut de l’objet, si notre classe se nomme « Membre », alors :

$membre = new Membre() ; // Appel de la méthode __construct() ;
echo $membre->nom ; // Appel de la méthode __get(‘nom’) ;

Affichera : « ex0ns »

Ainsi, pas besoin de créer un getter pour le nom et un pour le site, de plus, grâce à cette surcharge magique __get, vous pourrez traiter vos attributs directement dans la classe (pour éviter les failles XSS), par exemple, notre fonction pourrait devenir :

public fonction __get($value){
    if(array_key_exists($value,$this->public_attributes)){
        return htmlspecialchars($this->public_attributes[$value], ENT_QUOTES, ‘UTF8’);
        }
}

Ainsi, on réduit le nombre de répétition dans le code, et on évite les erreurs d’inattention qui, dans certains cas, peuvent s’avérer fatales.

Pour la methode __set($name, $value), le principe est similaire:

public function __set($name, $value){
    if(array_key_exists($name,$this->attributs))
        $this->attributs[$name] = $value;
}

Si votre classe a un lien avec la base de donnée (gestion de l’utilisateur par exemple) c’est dans cette méthodes que les requêtes UPDATE pourraient êtres faites.

Attention, si les attributs d’une classe ne sont à l’origine accessibles qu’a l’intérieur de cette dernière, c’est qu’il y a une raison, de sécurité principalement. Alors, je vous propose de créer une classe, qui a des attributs en « readonly » (get uniquement), et d’autres que l’on peut modifier (get + __set), pour cela, au lieu de créer un tableau attributs, nous allons en faire deux :

private $readOnly = array() ; // Contient les attributes qu’on ne peut que lire
private $attributs= array(); // Contient les autres attributs

On peut donc transformer notre fonction de get de cette facon:

public function __get($name){
    if(array_key_exists($name, $this->readOnly))
        return $this->readOnly[$name];
    if(array_key_exists($name, $this->attributs))
        return $this->attributs[$name];
}

Jusque là rien de nouveau, mais c’est au niveau de la methode __set que la méthode diffère légèrement.

public function __set($name, $value){
    if(array_key_exists($name, $this->attributs))
        $this->attributs[$name] = $value;
}

Donc là, on ne regarde que dans le tableau sur lequel nous avons les “droits” d’écriture, ce qui nous permet de garantir le controle sur les autres variables pour ce qui est de l'écriture.

Il existe d’autres opérateurs magiques en PHP, vous pourrez trouver la liste : ici