Getter et setter automatiques avec les méthodes magiques sous PHP 5
L' objet sous PHP 5 introduit de nouvelles methodes, dites magiques. Elles permettent de s'affranchir de tâches parfois fastidieuses telles que l'écriture de getter et de setter. Nous allons voir comment employer deux de ces méthodes.
L'un des avantages de l'objet est la possibilité d'en capsuler les données dans un objet et ainsi de pouvoir exercer un certain contrôle sur les accès qui sont effectués. Cependant, lorsque ces données deviennent nombreuses, l'écriture de toutes les méthodes d'accès peut devenir fastidieuse. Prenons un exemple assez simple :
class foo() { private $a; private $b; private $c; [...] private $z; }
Il nous faudrait, en principe, pas moins de 26 getter et 26 setter (soit 52 méthodes) pour pouvoir accéder à tous les attributs de cette classe. Il existe bien des outils qui permettent l'écriture automatisée des ces méthodes, mais on assistera alors à une belle surcharge de code.
C'est là qu'interviennent les méthodes __get() et __set().
La méthode __set()
Cette méthode reçoit deux paramètres, le nom de l'attribut auquel on souhaite accéder et la valeur que l'on souhaite lui donner. Reprenons donc avec notre exemple de classe :
class foo() { private $a; private $b; private $c; [...] private $z; public function __set($attr,$value) { if(isset($this->$attr)) $this->$attr = $value; else throw new Exception('Unknow attribute '.$attr); } }
Si l'attribut demandé n'existe pas, on lance une exception.
La méthode __get()
Cette méthode ne reçoit qu'un seul paramètre, c'est le nom de l'attribut qui a été appelé. Reprenons donc avec notre exemple de classe :
class foo() { private $a; private $b; private $c; [...] private $z; public function __get($attr) { if(isset($this->$attr)) return $this->$attr; else throw new Exception('Unknow attribute '.$attr); } }
Si l'attribut demandé n'existe pas, on lance une exception.
Réinventons stdclass
Stdclass est une classe définit par php. Elle permet de stocker autant d'attributs que l'on souhaite. Il est donc possible d'écrire le code suivant sans aucun problème :
$a = new stdclass; $a->foo = 10; echo $a->foo; // Affiche bien 10
Voici donc, à partir de ce que nous venons de voir, de quelle manière nous pourrions implémenter une telle classe. Pour éviter les conflits, nous la nommerons MyStdclass :
class MyStdclass { private $data; public function __construct() { $this->data = array(); } public function __set($key,$value) { $this->data[$key] = $value; } public function __get($key) { return $this->data[$key]; } }
Je ne lance pas d'erreur ici, logiquement PHP s'en chargera selon sa configuration, comportement adopté par stdclass. Mais rien n'empêche de lancer des erreurs en cas d'attribut indéfini.
Conclusion
Personnellement, l'emploi d'un tableau me parait plus propre plutôt que de définir de nouveau attribut. Un tableau est une structure naturellement dynamique en PHP et on sait que, quoi qu'il contienne, il conservera toujours la même visibilité. Quel est la visibilité de nouveaux attributs définit durant l'exécution? Bonne question, public j'imagine...
J'en ai déjà vu certains dire (ou plutôt écrire) que l'utilisation de tableaux rendait les écritures moins simples dans les méthodes. Oui mais, le fait de définir les méthodes __get() et __set() tel qu'indiqué ci-dessus, rend possible l'emploi de $this->indiceDuTableau, les écritures restent donc rigoureusement les mêmes qu'avec des attributs classiques.



Certain sont effectivement peu intime avec le
theresa | jeudi 17 décembre 2009 | 02:21Certain sont effectivement peu intime avec le concept d humour
c une des regle elemantaire du marche
sabre8 | vendredi 15 janvier 2010 | 11:05c une des regle elemantaire du marche
je ne suis pas sur que ton exemple avec les
edennnnn | mercredi 21 juillet 2010 | 14:36je ne suis pas sur que ton exemple avec les methodes magiques fonctionne
class foo()
{
private $a;
private $b;
private $c;
[...]
private $z;
public function __set($attr,$value)
{
if(isset($this->$attr)) $this->$attr = $value;
else throw new Exception('Unknow attribute '.$attr);
}
}
en effet isset($a) renverra faux si $a n est pas initialisé
Il me semble que isset() ne renvoie pas faux dans
Thierry Geindre | mercredi 21 juillet 2010 | 14:48Il me semble que isset() ne renvoie pas faux dans ce cas. Ceci dit, je ne jurerais de rien ! Ce billet commence à dater un peu, et, passée l'effervescence de la sortie de PHP5 (ou disons plutôt de la généralisation de php 5), j'en suis arrivé à la conclusion que les méthodes magique c'est à éviter. Comme tout ce qui se dit magique en PHP d'ailleurs