php-experts.org - développement php et internet » poo https://www.php-experts.org Ressources sur le développement internet, PHP/MySQL, Ajax, marketing online, référencement... Sat, 19 Jun 2010 14:23:03 +0000 http://wordpress.org/?v=2.9.2 en hourly 1 Coder une classe d’abstraction pour manipuler des objets en PHP5 https://www.php-experts.org/developpement-web/php-developpement-web/coder-une-classe-dabstraction-pour-manipuler-des-objets-en-php5-18 https://www.php-experts.org/developpement-web/php-developpement-web/coder-une-classe-dabstraction-pour-manipuler-des-objets-en-php5-18#comments Fri, 25 Jul 2008 20:38:22 +0000 Didier https://www.php-experts.org/?p=18 Sur chaque site, dans tous les projets, on a une base de données qui contient des tables, dont chaque ligne sont des items que l’on souhaitera manipuler à un moment où à un autre. Le code PHP à écrire pour effectuer les actions nécessaires – Ajouter des items, les modifier, les supprimer, récupérer leurs attributs… – varie peu, et pourtant ce travail est souvent répété d’un projet à l’autre. Il est possible de créer une classe générique d’abstraction, qui pourra manipuler toutes sortes d’objets de manière transparente.

Note: On m’a souvent déconseillé d’utiliser l’introspection (et donc notamment la méthode __get() ) pour des problèmes de performances. Or, et malheureusement, il est de nos jours nécessaire de se rappeler que l’hébergement d’un site, même si ses coûts pourraient être réduits par de l’optimisation poussée/poussive sur le code, coûtera bien moins cher qu’un développeur qualifié, à plein temps, occupé à maintenir du code “optimisé” mais dont on pourrait aisément se passer en achetant un serveur plus puissant. J’utilise donc __get et si ça vous choque, louez un serveur dédié (et en plus je me permets un lien d’affiliation…) et arrêtez de vous demander si vous devez utiliser echo ou print… Ce n’est pas là que sera votre valeur ajoutée en tant que développeur. Il est largement plus rentable à moyen et long terme de faire du code modulaire, réutilisable, en capitalisant sur les temps de développement.

Magic function : __get

Dans la programmation orientée objets en php5, il existe des méthodes de classes qui sont dites “magiques”. La plus célèbre, __construct(), est appélée à l’instanciation de la classe.
Une autre, moins connue, est appelée lorsqu’on tente d’accéder à une propriété qui n’est pas définie. C’est __get(). Cette méthode reçoit un argument, qui est le nom de la propriété en question. C’est celle-ci que nous allons utiliser pour réaliser notre classe d’abstraction. Pour l’exemple, nous assumerons que nous avons une variable globale (oui, je sais, encore quelque chose que je ne devrais pas faire… mais j’attends toujours qu’on m’explique pourquoi) $oDb qui est un objet Database capable de renvoyer la valeur d’une ligne (getRow) d’une table de la base de données.

Comme d’habitude, on va gérer une table Employes contenant des champs ID, nom, prenom et salaire (respectivement int, varchar, varchar et int…) :

  1. class GenericObject {
  2.     public function __get($var) {
  3.         print "Magic : get $var";
  4.     }
  5. }
  6. $emp = new GenericObject;
  7. print $emp->nom;

Comme on le voit, on essaye à la ligne 7 d’accéder à la propriété “nom”, alors que celle-ci n’existe pas. La méthode __get() est alors appelée et reçoit en argument le nom de la propriété inexistante (le script affichera donc bien Magic: get nom.

Dès lors, on peut imaginer construire une classe acceptant un nom de table (string) et un identifiant (integer) en argument et pouvant, déjà, rappatrier la valeur de n’importe quel champ. Imaginons le script suivant :

  1. class GenericObject {
  2.     public function __construct($table, $id) {
  3.         global $db;
  4.         // on charge la ligne de la base de données
  5.         $this->infos = $db->getRow("select * from $table where id = ‘$id’");
  6.     }
  7.     public function __get($var) {
  8.         // on renvoie la valeur tirée de la valeur (tableau) de la propriété $this->infos
  9.         return $this->infos[$var];
  10.     }
  11. }
  12. $emp = new GenericObject(‘emp’,1);
  13. var_dump(isset($emp->nom));
  14. print $emp->nom;

Ici, la classe est instanciée dans l’objet $emp. On lui passe l’ID (en base) de notre employé fictif. Dès lors, on peut, en une ligne, récupérer la totalité des informations le concernant. Pour preuve, la ligne 14 affiche bien “Dupont”. A noter, la ligne 13 qui renvoie bool(false) : $nom c’est vraiment pas défini avant le get.

Magic function : __set()

Bien sur, parralèlement à __get, on peut utiliser la méthode __set() pour changer la valeur d’une propriété qui n’est pas définie. Cette méthode accepte, cette fois, deux paramètres: le nom de la propriété en question et la valeur que l’on souhaite lui affecter. L’intérêt dans ce cas (pour différer du comportement “normal” de PHP, est, par exemple, de récupérer la liste des champs de la base dans une propriété, et de vérifier à chaque __set que la variable qu’on tente de déclarer aura bien une correspondance dans la table de la base de données.

Magic function : __destruct()

Quitte à utiliser des fonctions “magiques”, autant le faire jusqu’au bout. On peut, grâce à la méthode __destruct(), effectuer une action lorsque l’objet sera désinstancié. Cela peut se passer si on le unset, ou lorsque le script se terminera. Par exemple, pourquoi ne pas enregistrer les changements de notre objet dans la base de données ? Dans notre exemple, il suffit de faire une boucle foreach sur le tableau $this->infos et de formater une requête SQL UPDATE.

Bon, certes, j’ai pris pas mal de raccourcis, donc le code n’est pas vraiment exploitable “tel quel”, mais avouez que la classe est efficace dans le sens où elle peut gérer toutes sortes d’objets. Il faudrait notamment ajouter, avec __set, le système qui vérifie que le champ existera dans la table (en récupérant son type pour faire des contrôles avant d’insérer). Dans le __destruct, il faut faire en sorte de ne sauver que les champs ayant été modifiés. Et bien sur, éviter l’édition de l’ID sur un objet que l’on vient de charger. Tout un programme ;)
On pourrait par exemple utiliser ce système pour gérer les utilisateurs d’un site, avec gestion des droits en bit bashing.

On pourrait coder par-dessus tout ça un système d’itérateurs pour les gérer en lots. (et effectuer simplement des tâches comme “Afficher tous les employés”, “Augmenter tout le monde de 100 €”, etc).

Je tiens mon “work in progress” (WIP©) de la classe à disposition pour qui voudra, n’hésitez pas à me le demander dans les commentaires ou par mail. :)

]]>
https://www.php-experts.org/developpement-web/php-developpement-web/coder-une-classe-dabstraction-pour-manipuler-des-objets-en-php5-18/feed 8