Integration of PHP Namespaces » History » Version 3

moyo, 10/02/2013 08:02 AM

1 1 webmyster
h1. Utilisation des espaces de nom (GLPI >= 5.3)
2 1 webmyster
3 1 webmyster
Les espaces de nom PHP permettent de regrouper des classes dans une même entitée. Ils évitent de "polluer" l'espace de nom global par des éléments appartenant à des composants bien délimités. Par exemple, les composants extérieurs (Zend, ezComponent, ...) contiennent des classes dont les noms pourraient entrer en conflit avec ceux de GLPI. D'une autre côté, la classe @HTMLTable_@ contient un certain nombre de sous-composants (@Table@, @Row@, @Cell@, @Header@, ...) qui n'intéressent que la classe @HTMLTable_@. En d'autres termes, que ce soit pour les classes des composants extérieurs comme celles de composants interne, il s'agit de "détails d'implémentation" qui n'ont aucune signification hors du contexte spécifique du package.
4 1 webmyster
5 1 webmyster
Dans le cadre de GLPI, nous pourrions les utiliser pour créer des "packages" homogènes. Par exemple, nous pourrions avoir un "package" @OCS@ qui regrouperait toutes les classes gérant l'interface avec OCS. Un autre package intéressant serait @HTMLTable@, dont le but est de gérer des tableaux HTML automatiquement.
6 1 webmyster
Comme le suggère Moyo (dans [[AutoLoad]]), un namespace @Plugin@ prendrait en charge tous les plugins.
7 1 webmyster
8 1 webmyster
h1. Utilisation d'un espace de nom dans PHP
9 1 webmyster
10 1 webmyster
Pour créer l'object @Table@ qui appartient à l'espace de nom @HTMLTable@, il suffit de faire @new HTMLTable\Table()@. Les espaces de nom peuvent être imbriqués. Par exemple, nous pourrions avoir la classe @Plugin\MassOCSImport\Server@.
11 1 webmyster
Une classe définie dans un espace de nom appel simplement les autres classes du même espace de nom. Donc, dans le namespace @HTMLTable@, la classe @Row@ hérite simplement de ma classe @Entity@, elle même définie dans le namespace @HTMLTable@.
12 1 webmyster
Pour faire appel à une classe à la racine, il suffit de préfixer son nom par '\'. Ainsi, la classe @HTMLTable\Cell@ peut faire appel à @\Session::addToNavigateListItems(...)@.
13 1 webmyster
14 1 webmyster
Il y a une chose à laquelle il faut faire très attention : PHP, comme le langage C, prend le caractère '\' comme caractère d'échappement. Par exemple '\n' correspond au retour à la ligne. Cela pose beaucoup de problèmes. En effet, lorsque l'on utilise une variable comme nom de classe dans un namespace, il faut, soit doubler les '\' dans les chaines de caratères encadré de double quotes, soit utiliser des simples quotes.
15 1 webmyster
16 1 webmyster
h2. Problèmes avec les @$_GET@ et @$_POST@
17 1 webmyster
18 1 webmyster
Le problème précédent est d'autant plus crucial avec les formulaires HTML : un champs contenant, par exemple, @NetworkPort\Ethernet@, renverra la valeur @NetworkPort\\Ethernet@ dans les variales @$_POST@, @$_GET@ et @$_REQUEST@. Il faut donc penser à utiliser, systématiquement @stripslashes@ sur ce type de champs.
19 1 webmyster
20 1 webmyster
h1. Interaction avec la base de données SQL
21 1 webmyster
22 1 webmyster
h2. Noms des tables associés aux espaces de noms
23 1 webmyster
24 1 webmyster
Dans ses versions les plus récentes, MySQL autorise le symbole '\' dans le nom des tables à la condition que le nom soit "quoté" (ie : entouré par '`'). Grâce au lourd travail de "Coding Standard", c'est maintenant quasiment le cas sur l'ensemble du coeur.
25 1 webmyster
Donc, la fonction @getTableForItemType@ fonctionne sans problème sur les espaces de noms. Ainsi, la table associée à l'élément @NetworkPort\Alias@ serait @`glpi_networkport\aliases`@.
26 1 webmyster
27 1 webmyster
Si on veut pousser le formalisme plus loin, nous pourrions remplacer le préfixe @glpi_@ des tables de GLPI par @glpi\@. Ainsi, nous pourrions considérer la table @`glpi\networkport\aliases`@ comme la table associée à la classe @Alias@, du composant @NetworkPort@, de @GLPI@. Mais cette dernière évolution est une autre histoire ...
28 1 webmyster
29 1 webmyster
h2. Problème des classes utilisées en tant que valeur dans les tables
30 1 webmyster
31 1 webmyster
De même que PHP et C, MySQL utilise le '\' comme caractère d'échappement. Donc, tous les champs de même nature que les champs @`itemtype`@ poseront problème lorsque les 'items' sont des classes dans des espaces de nom.
32 1 webmyster
L'une des solution est de modifier les méthodes @CommDBTM::AddToDB@ et @CommonDBTM::updateInDB@ pour faire un @addslashes@ sur toutes les valeurs intégrées dans les requètes SQL. Mais les effets de bord risquent d'être redoutables. Entre autre, comment vont se comporter des champs comme @`comment`@ qui ont des retours à la ligne ('\n') ?
33 1 webmyster
Une autre solution est de faire en sorte, dans la classe où on utilise ce type de champs, de préparer la valeur avant de la soumettre à MySQL.
34 1 webmyster
35 1 webmyster
h1. Organisation des fichiers
36 1 webmyster
37 1 webmyster
Nous avons vu que les espaces de noms permettaient d'isoler des composants "autonomes". Cette isolation pourrait faire l'objet d'une arborescence à part. Ainsi, à chaque espace de nom correspondrait un sous-répertoire du répertoire @$GLPI_ROOT/inc@. Il faudra limiter le nombre d'espaces de nom afin de ne pas multiplier les répertoires et alourdir la navigation. Mais il ne faut pas oublier, non plus, qu'un espace de nom correspond à un composant autonome dont l'interface est relativement figée. Ainsi, soit on travail sur le composant en question, soit on l'utilise. Mais nous devrions rarement avoir besoin d'ouvrir des fichiers dans le coeur et dans plusieurs composants en même temps. Donc, la navigation devrait être relativement restreinte.
38 1 webmyster
39 1 webmyster
h2. Mise en oeuvre
40 1 webmyster
41 1 webmyster
Pour mettre en oeuvre cette solution hiérarchique, il suffira d'une petite mise à jours des functions @glpi_autoload@ et @isPluginItemType@. En effet, dans la première, il suffit de remplacer '\' (en fait '\\' car '\' est un caractère d'échappement) par '/' dans le nom du fichier à charger pour atteindre la classe. Dans la seconde function (@isPluginItemType@), il faut autoriser, également, '\' comme caractère valide dans le nom d'une classe.
42 1 webmyster
43 1 webmyster
h1. les plugins
44 1 webmyster
45 1 webmyster
Dans l'idée proposée par MoYo, les plugins étaient gérés par des namespaces. Un namespace global @Plugin@ pourrait contenir tous les plugin. Chacun des plugins aurait son propre espace de nom dans l'espace de nom @Plugin@. Par, le plugin Mass OSC Import et IPAM auraient respectivement @Plugin\MassOSCImport@ et @Plugin\IPAM@ comme espace de nom. Afin de rester cohérent en termes de composants, le gestionnaire de plugin (actuellement la classe Plugin) serait renommé en @Plugin/Manager@.
46 1 webmyster
47 1 webmyster
h1. les composants extérieurs
48 1 webmyster
49 1 webmyster
Malheureusement @Zend@ et @ezComponent@ n'utilisent pas les espaces de noms. Sinon, le filtre dans @glpi_autoload@ serait grandement simplifié : pour chaque classe, on extrait son namespace (ie : mot juste avant le premier '\') et un simple @switch@ permettrait de savoir s'il s'agit d'un composant Zend, ezComponent, ou bien, même, d'un plugin.
50 2 remi
51 2 remi
Remi: Zend 2 utilise désormais les namespaces. Il me semble intéressant de respecter le standard PSR0 ce qui pourra permettre d'utilise un autoloader standard (ex, celui de ZF2) https://github.com/php-fig/fig-standards/blob/master/accepted/fr/PSR-0.md
52 3 moyo
MoYo : pourquoi pas mais je trouve bizarre la recommandation liée au sous-tiret