Chapitre 7. Hoa_Configuration
Toutes les applications sont basées sur des fichiers de configuration. Ces fichiers permettent de modifier la façon dont l'application va se comporter et sont donc nécessaires si on veut une application orientée utilisateur.
Les fichiers de configuration sont souvent écrits dans les formats XML, INI, PHP ou encore YAML. Hoa propose de lire ces fichiers, et de les consulter de façon simple et rapide.
Sortie standard des configurations
Pour une utilisation plus souple et plus facile des fichiers de configuration, Hoa a adopté une sortie standard quelque soit le type de fichier de configuration. C'est à dire que si on utilise un fichier XML, YAML, PHP ou INI, la façon d'exploiter les données du fichier seront identiques.
Préparer la lecture
Pour faciliter l'utilisation du paquetage
Hoa_Configuration, on ne se base pas sur une fabrique,
mais sur les règles de nommages.
Ainsi, tous les paquetages commencent par :
Hoa_Configuration_ et sont suivis du format que l'on
souhaite utiliser. Si on veut utiliser le format INI,
alors on demandera l'instance du paquetage :
Hoa_Configuration_Ini, et ainsi de suite pour les autres
formats. On aura quelque chose de semblable à :
<?php set_include_path( ... ); require_once 'Framework.php'; import('Configuration.Ini'); /** * On demande l'instance de la * configuration des fichiers INI. */ $config = new Hoa_Configuration_Ini( ... );
Chaque objet de configuration par type de fichier a un constructeur différent. Cela se conçoit facilement, car chaque type de fichier n'a pas les mêmes besoins d'analyse ; un tableau se lit de façon naturelle, alors qu'un fichier INI a besoin de paramètres de lecture.
Sortie en objet Hoa_StdClass
Il y a deux façons d'exploiter les données de configurations. La
première, et celle par défaut, est la sortie en objet
Hoa_StdClass. Cet objet offre des possibilités qui
ne sont pas forcément évoquées ou détaillées dans ce chapitre, on
conseille alors de lire le Chapitre 25, Hoa_StdClass.
Accès aux variables
L'objet Hoa_StdClass se comporte comme
l'objet StdClass de PHP en
offrant des possibilités supplémentaires. Tout d'abord, on va regarder
comment on accède aux données :
/** * Soit la structure suivante : */ ( 'a' => 'AaA', 'b' => 'bBb', 'c' => ( 'x' => 'XxX', 'y' => 'yYy', 'z' => 'Zzz' ) ); /** * Alors on atteint les données de * cette façon : */ echo $structure->c->y;
Cela nécessite, dans le cas de la sortie
Hoa_StdClass, que toutes les « clés » respectent le motif des
variables de
PHP, à savoir :
[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*
Si ce n'est pas le cas, une exception
Hoa_StdClass_Exception sera levée.
La racine des configurations s'obtient en appelant la méthode
get de l'objet
Hoa_Configuration.
Parcourir les configurations
L'objet Hoa_StdClass implémente l'interface
Iterator ce qui nous permet de placer les
configurations dans des boucles afin de le parcourir :
$config = new Hoa_Configuration_xxx( ... ); /** * On parcourt tout le sous-niveau c. */ foreach($config->c as $key => $value) echo $key . ' : ' . $value . "\n";
Les configurations peuvent être sous forme d'arbre, donc lors
d'un parcours, la valeur peut être un nouvel arbre. Pour savoir si
c'est le cas, Hoa_Configuration propose la
méthode isRecursive qui retourne
true s'il y a un sous-arbre, un sous-niveau,
false sinon.
Afficher les configurations
Pour se représenter plus facilement l'arbre des configurations sous forme d'objet, on peut l'afficher directement. Le résultat ressemblant sensiblement à la sortie de print_r :
echo $config; /** * Affichera : * * Hoa_StdClass ( * [a] => AaA * [b] => bBb * [c] => Hoa_StdClass ( * [x] => XxX * [y] => yYy * [z] => Zzz * ) * ) */
Transformer l'objet en tableau
Il peut arriver que l'on veuille transformer notre sortie objet
en tableau. Pour ça, l'objet Hoa_StdClass propose
la méthode toArray. Il faut appliquer cette
méthode sur un nœud ou à la racine des configurations :
/** * On transforme nos configurations sous forme d'objet * vers un tableau. */ print_r($config->get()->toArray()); print_r($config->c->toArray());
Sortie en tableau
Par défaut, la sortie est sous forme d'objet
Hoa_StdClass, mais on a la possibilité de désactiver
cette conversion à l'aide du dernier paramètre de chaque constructeur :
CONVERT_TO_OBJECT pour activer la conversion,
CONVERT_TO_ARRAY sinon. Ces constantes sont
disponibles sur la classe Hoa_Configuration.
Manipulation des données
L'accès aux variables, le parcours des configurations, ou l'affichage se fait de façon naturelle, à l'aide des fonctions PHP, à savoir :
/** * On désactive la conversion en objet. */ $config = new Hoa_Configuration_xxx( ... , ... , Hoa_Configuration::CONVERT_TO_ARRAY); /** * On accède aux données. */ echo $config['c']['y'] . "\n"; /** * On parcours les configurations. */ foreach($config['c'] as $key => $value) echo $key . ' : ' . $value . "\n"; /** * On affiche les configurations. */ print_r($config['c']);
Pour atteindre la racine des configurations, on appelle
également la méthode get.
Pour savoir s'il y a un sous-niveau, on utilise également la
méthode isRecursive.
La méthode get
Si on veut atteindre le niveau 0 (la racine) des configurations,
on doit appeller la méthode get sur notre objet de
configuration.
À partir d'un tableau
On a vu que les configurations peuvent être stockées sous différentes formes. Une des formes les plus simples est un tableau déclaré en PHP.
On procéderait de la façon suivante :
<?php set_include_path( ... ); require_once 'Framework.php'; import('Configuration.Array'); $array = array( 'a' => 'AaA', 'b' => 'bBb', 'c' => array( 'x' => 'XxX', 'y' => 'yYy', 'z' => 'Zzz' ) ); $config = new Hoa_Configuration_Array($array); echo 'En mode : ' . $config->c->z; /** * Affichera : * En mode : Zzz */
Il est préférable pour de moyennes ou grosses applications d'écrire
les configurations dans un fichier à part. On appelle
Config.php ce fichier, et il sera de la forme suivante :
<?php return array( 'a' => 'AaA', 'b' => 'bBb', 'c' => array( 'x' => 'XxX', 'y' => 'yYy', 'z' => 'Zzz' ) );
Alors on aura simplement à faire :
$config = new Hoa_Configuration_Array(require 'Config.php');
Ce qui reviendra au même. L'exploitation des données restera la même que précédemment.
Si on veut préférer une sortie sous forme d'un tableau plutôt que de
l'objet Hoa_StdClass, il suffit de passer un second
paramètre : un booléen à faux :
$config = new Hoa_Configuration_Array( require 'Config.php', Hoa_Configuration::CONVERT_TO_ARRAY ); echo 'En mode : ' . $config['c']['z'];
À partir d'un fichier INI
Exploitation des données
On peut également exploiter les configurations stockées dans un fichier INI. Pour cela, on procédera de la façon suivante :
<?php set_include_path( ... ); require_once 'Framework.php'; import('Configuration.Ini'); $config = new Hoa_Configuration_Ini('Config.ini');
Si on veut reprendre les exemples précédents, alors le fichier
Config.ini ressemblera à ceci :
a = AaA b = bBb c.x = XxX c.y = yYy c.z = Zzz
Accéder à une catégorie
Les fichiers INI peuvent être construits en catégories, i.e. partagées en plusieurs parties :
[db] host = localhost user = root pwd = dbname = base [lang] locale.timezone = Europe/Paris locale.region = Franche-Comté locale.departement = Doubs encoding = utf-8
Pour simplifier les traitements, on peut manipuler seulement une
seule catégorie. Pour cela, on passe le nom de la catégorie en second
paramètre du constructeur de Hoa_Configuration_Ini :
$config = new Hoa_Configuration_Ini('Config.ini', 'db'); /** * On ne parcourt que les configurations * de la base de données. */ foreach($config->get() as $key => $value) echo $key . ' ' . $value . "\n";
Et enfin, le troisième paramètre sert à désactiver la sortie sous
forme de l'objet Hoa_StdClass pour activer la sortie
sous forme d'un tableau :
$config = new Hoa_Configuration_Ini('Config.ini', 'db', Hoa_Configuration::CONVERT_TO_ARRAY); foreach($config->get() as $key => $value) echo $key . ' ' . $value . "\n";
Échapper les points
On remarque que le point (.) est le séparateur de niveau dans les fichiers INI. Il est possible de les échapper avec Hoa, en les précédent d'un anti-slash (\) :
on.echappe\.un.point = hopla
Attention, si le fichier est converti en
Hoa_StdClass le point sera transformé en trait de
soulignement (underscore, _).
À manipuler avec précaution donc.
À partir d'un fichier XML
XML est un langage de sérialisation plutôt pratique car très répandu. En général, les autres langages le comprennent assez bien, et il a l'avantage de se présenter directement comme un arbre.
Exploitation des données
L'analyse des fichiers XML se fait à l'aide du paquetage
Hoa_Xml (voir le Chapitre 31, Hoa_Xml). Le
constructeur de Hoa_Configuration_Xml prend donc en
premier paramètre le fichier qui contient les configurations, puis
l'encodage du fichier, et pour finir l'activation de la conversion vers
une sortie objet :
import('Configuration.Xml'); $config = new Hoa_Configuration_Xml('Config.xml');
On aurait un fichier qui ressemblerait à (avec une en-tête qui précise la version et l'encodage) :
<configuration> <db> <host>localhost</host> <user>root</user> <pwd></pwd> <dbname>base</dbname> </db> <lang> <locale> <timezone>Europe/Paris</timezone> <region>Franche-Comté</region> <departement>Doubs</departement> </locale> <encoding>utf-8</encoding> </lang> </configuration>
Et on accéderait aux données de cette façon :
echo $config->lang->locale->region . "\n"; /** * Affichera : * Franche-Comté */
Le problème avec les nombres
Dans XML, il peut arriver que l'on ait plein de
fois la même balise à un même niveau, c'est ce qu'on appelle le
multi-balisage[8]. Dans ce cas, on a une liste ordonnée des
balises (on conseille vraiment d'aller voir le chapitre concerné). Dans
le cas d'une sortie Hoa_StdClass, les variables ne
peuvent pas être entières[9]. La solution qui a été retenue
est de préfixer les entiers par un trait de soulignement
(underscore, _), si on a demandé cette sortie. Pour
un tableau rien ne change.
On pourrait alors avoir :
<configuration> <test> <bidule>machin</bidule> </test> <test> <truc>hopla</truc> </test> </configuration>
On y accéderait de cette façon :
echo $config->test->_0->bidule; /** * Affichera : * machin */
On rappelle que ce problème n'a pas lieu avec une sortie en tableau.
À partir d'un fichier YAML
YAML est un langage de sérialisation très pratique car orienté humain. C'est un langage suffisament puissant pour nous servir de fichier de configuration. On trouvera plus d'informations sur le langage en lisant sa spécification : Specification of YAML Ain't Markup Language (YAML) Version 1.1.
Exploitation des données
Hoa_Configuration_Yaml analyse les fichiers à
l'aide du paquetage Hoa_Yaml (voir le Chapitre 33, Hoa_Yaml), on retrouve donc les mêmes options que le
constructeur pour le constructeur de
Hoa_Configuration_Yaml (avec, en plus, la possibilité
de ne pas convertir les configurations en objet
Hoa_StdClass).
On aura quelque chose de semblable à ça :
import('Configuration.Yaml'); $config = new Hoa_Configuration_Yaml('Config.yml');
On aurait un fichier de configuration qui serait susceptible de ressembler à ceci :
host: localhost user: root pwd: dbname: base
On accéderait aux données de cette façon (comme déjà vu précédemment) :
echo $config->host . "\n";
Accéder à un document
Un document YAML peut contenir plusieurs sous-documents, comme si le fichier en contenait plusieurs autres. Ces documents sont numérotés de 0 à n, et on y accède en passant un entier en second paramètre du constructeur. Par défaut, on sélectionne le premier document (donc d'index 0).
On aurait alors :
$config = new Hoa_Configuration_Yaml('Config.ini', 2);
On rappelle que les documents sont séparés par trois traits d'union
(---) :
# Premier document (index 0). --- host: localhost user: root pwd: dbname: base # Second document (index 1). --- etc: bla bla bla
Et enfin, le dernier paramètre spécifie si on veut que les
configurations soient converties en objet
Hoa_StdClass ou pas. Pour avoir un tableau en
sortie, on aura :
$config = new Hoa_Configuration_Yaml('Config.yml', 0, Hoa_Configuration::CONVERT_TO_ARRAY);
Le problème avec les nombres
Dans YAML, on travaille beaucoup avec des
listes ordonnées. Le problème, si on a choisi une sortie
Hoa_StdClass, est que les nombres ne peuvent pas
constituer une variable[10].
La solution qui a été trouvée est que tous les nombres sont préfixés d'un
trait de soulignement (underscore, _) si on a demandé
cette sortie. Pour un tableau, rien ne change.
On pourrait alors avoir :
bob: - bill: le chien - billy: le crabe
On y accéderait de cette façon :
echo $config->bob->_1->billy; /** * Affichera : * le crabe */
On rappelle que ce problème n'a pas lieu avec une sortie en tableau.

