Variables read-only dans une classe PHP

Pour ceux d’entre vous qui font du PHP le moindrement sérieusement, vous avez sans doute remarqué que PHP manque quelque chose du coté de la POO.

C, Visual Basic, C#, et plusieurs autres langages ont la capacité d’avoir des variables publiques en lecture seule dans une classe. C’est à dire que la variable peut être modifié à l’intérieur de la classe, mais à l’extérieur on ne peut que la lire !
Prenons l’exemple suivant:

J’ai une classe qui s’appelle utilisateur et qui gère une session utilisateur:

Class utilisateur {

[....]

public $id = 0;

public $nom = ”;

[....]

}

Admettons que les valeurs de $nom et $id proviennent d’une base de données, il serait fort probablement utile de pouvoir y accéder depuis l’extérieur de la classe! Bref j’aimerais pouvoir lire $nom et $id mais je ne veux pas qu’elles puissent être modifier à l’extérieur de la classe (cela pourrait causer des erreurs, des problèmes de sécurité, des problèmes de conception, etc).

Par exemple:

echo “Je suis  {$utilisateur->nom} et mon id est {$utilisateur->id}”;

Mais en les mettant publique, il y a un problème, on peut aussi les modifier depuis l’extérieur de la classe. Parfois cela est voulu, mais souvent cela pourrait provoquer des erreurs.

$utilisateur->nom = ‘robert’;

echo “Je suis  {$utilisateur->nom} et mon id est {$utilisateur->id}”;

Une solution à ce problème serait l’utilisation de getters, mais cela est très peu pratique si nous avons beaucoup de variables.

Par exemple:

Class utilisateur {

[....]

private $id = 0;

private $nom = ”;

public function getNom(){

return $this->nom;

}

public function getId(){

return $this->id;

}

[....]

}

echo ‘Je suis  ‘.$utilisateur->nom().’ et mon id est ‘.$utilisateur->id();

À force de me creuser les méninges, j’en suis venu à une idée basée sur l’utilisation des méthodes magiques. (Pour ceux qui ne connaisse pas, les fonctions __get et __set sont appelées lorsqu’aucune variable publique ne correspond à celle demandé). Une petite astuce permet d’avoir des variables en readonly sans avoir recours à un getter pour chaque variable!

exemple:

Class utilisateur {

[....]

private $id = 0;

private $nom = ”;

public function __get($name){

return $this->$name;

}

[....]

}

echo “Je suis  {$utilisateur->nom} et mon id est {$utilisateur->id}”;

$toto->nom = ‘robert’; // Va retourner une erreur :)

Et voilà, c’est magique ! Il reste un inconvénient (mais qui est facilement contournable) : On ne veut pas forcément donner accès à toutes nos variables privée publiquement, même si ce n’est qu’en lecture ! Il y a plusieurs façons de contourner ça, par exemple précéder toutes ses variables publiques+readonly par un underscore:

public function __get($name){

if ($name[0] === ‘_’) return $this->$name;

}

Ou encore utiliser un array de variable readonly (mais ce n’est pas forcément performant…):

public function __get($name){

$readonly = array(’id’,'nom’);

if (in_array($name,$readonly)) return $this->$name;

}

Les exemples dans cet article devrait être complété avec des vérifications d’erreurs, des isset et l’appel à quelques autres méthodes magiques, mais dans un soucis de simplicité je n’expliquerai pas tout dans cet article :P

Enfin bref, vous comprennez le principe, à vous de vous amusez :)

Bonne prog !

Leave a Reply