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.