Moteur de templates de PHPBoost
Table des matières
La partie interface utilisateur de PHPBoost est régie par un système de templates. Le dossier présentant l'architecture technique de PHPBoost vous aidera certainement à situer cette couche et à comprendre son intérêt.
L'utilisation de fichiers templates n'est en rien obligatoire pour développer un CMS. Pourtant nous avons fait le choix d'utiliser ce principe de fonctionnement pour des raisons assez simples : PHPBoost se veut un portail entièrement personnalisable sur le plan graphique.
Il aurait été possible d'utiliser une feuille de style CSS par thème et les designs auraient pu être modifiés. Bien que ce soit le CSS qui gère la mise en forme, nous avons tout de même voulu laisser l'utilisateur pouvoir modifier la source HTML de ses pages afin notamment de déplacer les variables, ce qui n'aurait pas été possible avec du CSS. Nous avons fait le choix d'utiliser des templates, ce qui consiste à séparer complètement le PHP et le HTML. Quand on développe de façon traditionnelle le PHP permet de travailler sur le contenu des variables, mais le code HTML se trouve complètement mélangé au PHP, ce qui rend plus complexe la lecture du code. L'utilisation des templates a l'avantage de pouvoir laisser l'utilisateur modifier le code HTML de chacun de ses thèmes séparément, mais il permet en plus de clarifier le code PHP qui ne contient plus de HTML.
Rien de vaut un schéma pour comprendre comment se passe la séparation des deux parties du code.
Template signifie en français patron, à prendre dans le sens géométrique du terme. Cela correspond bien à ce qui est décrit, à savoir un dispositif de balisage pour placer les variables.
Le moteur de templates de PHPBoost utiliser une syntaxe qui lui est spécifique. Elle permet de symboliser des marqueurs qui seront remplacés lors du traitement par la valeur correspondante. Les paragraphes suivants permettent de détailler cette syntaxe.
Depuis PHPBoost 3.0, le moteur de templates a subi de grosses améliorations en terme de performance. L'inteprétation des fichiers template étant assez complexe, la mise en cache permet de ne l'effectuer qu'une seule fois par fichier en sauvegardant le fichier sous sa forme interprétée (un fichier PHP). Ensuite l'affichage est très rapide car il exploite directement le moteur d'interprétation de PHP (Zend engine) qui est très performant en incluant directement le fichier PHP mis en cache.
Ainsi, l'utilisation de templates n'est pas franchement plus lourde que le mélange du HTML et du PHP dans les fichiers et procure une nettement meilleur lisibilité et maintenabilité du code source.
Voyons maintenant comment utiliser le moteur de templates. Il est important de noter que du côté de PHP les templates sont gérés par la classe Template dont la documentation est ici.
Pour charger un fichier template, il suffit d'instancier un objet Template en lui indiquant le chemin du fichier.
Exemple :
Cela chargera le fichier file.tpl du dossier templates de votre module.
Il existe deux modes de traitement du fichier. Par défaut, le traitement aura pour effet d'écrire sur la sortie standard (donc ce qui sera envoyé au client) le résultat, mais il est également possible de récupérer le résultat sous forme de chaîne plutôt que de l'afficher. Le traitement se fait via la méthode parse() de la classe Template.
Exemple :
Les variables simples permettent de placer du contenu dans un fichier template.
Côté fichier template, il faut placer le nom de la variable entre accolades. Ainsi,
Côté PHP, l'assignation d'une variable se fait via la méthode assign_vars().
L'exemple suivant montre l'utilisation de variables simples.
Fichier template :
L'assignation dans le fichier PHP :
Le résultat de l'interprétation donne ceci :
Les boucles permettent de répéter une partie de code dans le template. Pour définir une boucle il faut respecter la syntaxe suivante.
Les boucles peuvent être imbriquées. Pour définir une boucle imbriquée il faut respecter la syntaxe suivante.
Les variables dans les boucles doivent être préfixées par la liste des boucles par lesquelles elles ont été assignées, séparées par des points.
Côté PHP, il faut utiliser la méthode assign_block_vars().
Prenons la boucle simple suivante :
L'assignation correspondante sera la suivante :
L'interprétation de ce template donnera
Prenons un second exemple avec une boucle imbriquée :
Le code PHP correspondant pourrait être :
L'exécution de ce code donnerait alors :
Bien que les conditions puissent être gérées par des boucles (une boucle assignée 0 ou 1 fois est une condition), il existe également la possibilité de définir des conditions dans les templates. Pour cela, il suffit d'assigner des variables dont les valeurs sont booléennes. Par convention, on les préfixe par C_.
Voici un exemple
Le code PHP ci-dessus génèrerait
On peut également faire des variables dans des boucles, en voici un exemple.
Vous avez compris que l'exemple donnerait :
Sur PHPBoost 3.1, il est possible d'inclure à un endroit d'un template le résultat de l'interprétation d'un autre template. sur PHPBoost 3.0, c'est aussi possible, mais la façon de le faire est largement dépréciée et nous n'expliquons donc pas comment le faire, il est cependant assez simple de contourner le problème, nous allons le voir dans l'exemple.
Voyons donc cela sur un exemple.
fichier1.tpl :
fichier2.tpl :
Côté PHP, nous avons :
Cela donne :
A noter que c'est strictement équivalent à remplacer
Pour charger un fichier, il faut utiliser le constructeur de la classe Template en utilisant un chemin de la forme suivante : mymodule/file.tpl. Cela aura pour effet de charger le fichier file.tpl de votre module se trouvant dans le dossier /mymodule/templates/.
Mais lors de la création d'un nouveau thème, il est possible qu'un template soit redéfini. Dans ce cas-là, il se trouvera dans /templates/mytheme/modules/mymodule/file.tpl. En fait, si ce dernier existe, il sera choisi en priorité, sinon celui par défaut du module sera utilisé (celui présent dans /mymodule/templates/file.tpl).
Cela a pour effet notamment que l'emplacement du thème change. Si celui-ci utilise des images qui sont également redéfinies, leur chemin ne sera pas le même que dans le thème par défaut. Pour cela, le moteur permet de connaitre où se situent les images. Dans la version 3.0 de PHPBoost, cette information est disponible avec la méthode Template::get_module_data_path(string $module) alors que pour PHPBoost 3.0, une variable template (
Il est à noter que si une image est redéfinie, elles doivent toutes l'être car la vérification n'est pas faire au cas par cas.
Il est possible de redéfinir les templates du framework. Pour cela, il suffit de le redéfinir dans le dossier /templates/mytheme/framework/ en recréant l'arborescence depuis là comme par exemple /templates/mytheme/framework/menus/content/display.tpl. Toutes les pages utilisant ce thème utiliseront alors ce template plutôt que celui par défaut (dans le répertoire /templates/default/).
Il est aussi possible de redéfinir le comportement du framework au sein d'un module. Pour cela, il faut redéfinir dans l'arborescence template du module le template en recréant son arborescence. Par exemple /mymodule/templates/framework/menus/content/display.tpl sera utilisé en priorité si il existe. On peut même redéfinir l'utilisation d'un template du framework dans un module pour un thème en le plaçant ici : /templates/mytheme/modules/mymodule/framework/menus/content/display.tpl
En résumé, voici les endroits où le moteur de templates va charger le template (si un il n'est pas trouvé à un emplacement il passe au suivant, jusqu'au dernier qui existe forcément) avec le chargement suivant :
Il est donc absolument possible de redéfinir l'apparence du framework et son comportement au sein même d'un module sans affecter les autres. Les possibilités de personnalisation du moteur de template permettent de spécialiser modules et thèmes de façon à pouvoir faire ce que l'on souhaite.
Pourquoi utiliser des templates ?
L'utilisation de fichiers templates n'est en rien obligatoire pour développer un CMS. Pourtant nous avons fait le choix d'utiliser ce principe de fonctionnement pour des raisons assez simples : PHPBoost se veut un portail entièrement personnalisable sur le plan graphique.
Il aurait été possible d'utiliser une feuille de style CSS par thème et les designs auraient pu être modifiés. Bien que ce soit le CSS qui gère la mise en forme, nous avons tout de même voulu laisser l'utilisateur pouvoir modifier la source HTML de ses pages afin notamment de déplacer les variables, ce qui n'aurait pas été possible avec du CSS. Nous avons fait le choix d'utiliser des templates, ce qui consiste à séparer complètement le PHP et le HTML. Quand on développe de façon traditionnelle le PHP permet de travailler sur le contenu des variables, mais le code HTML se trouve complètement mélangé au PHP, ce qui rend plus complexe la lecture du code. L'utilisation des templates a l'avantage de pouvoir laisser l'utilisateur modifier le code HTML de chacun de ses thèmes séparément, mais il permet en plus de clarifier le code PHP qui ne contient plus de HTML.
Rien de vaut un schéma pour comprendre comment se passe la séparation des deux parties du code.
Template signifie en français patron, à prendre dans le sens géométrique du terme. Cela correspond bien à ce qui est décrit, à savoir un dispositif de balisage pour placer les variables.
Principe de fonctionnement
Syntaxe spécifique
Le moteur de templates de PHPBoost utiliser une syntaxe qui lui est spécifique. Elle permet de symboliser des marqueurs qui seront remplacés lors du traitement par la valeur correspondante. Les paragraphes suivants permettent de détailler cette syntaxe.
Un traitement rapide
Depuis PHPBoost 3.0, le moteur de templates a subi de grosses améliorations en terme de performance. L'inteprétation des fichiers template étant assez complexe, la mise en cache permet de ne l'effectuer qu'une seule fois par fichier en sauvegardant le fichier sous sa forme interprétée (un fichier PHP). Ensuite l'affichage est très rapide car il exploite directement le moteur d'interprétation de PHP (Zend engine) qui est très performant en incluant directement le fichier PHP mis en cache.
Ainsi, l'utilisation de templates n'est pas franchement plus lourde que le mélange du HTML et du PHP dans les fichiers et procure une nettement meilleur lisibilité et maintenabilité du code source.
Utilisation du moteur de templates
Voyons maintenant comment utiliser le moteur de templates. Il est important de noter que du côté de PHP les templates sont gérés par la classe Template dont la documentation est ici.
Chargement d'un fichier
Pour charger un fichier template, il suffit d'instancier un objet Template en lui indiquant le chemin du fichier.
Exemple :
Code PHP :
$tpl = new Template('mymodule/file.tpl');
Cela chargera le fichier file.tpl du dossier templates de votre module.
Traitement d'un fichier
Il existe deux modes de traitement du fichier. Par défaut, le traitement aura pour effet d'écrire sur la sortie standard (donc ce qui sera envoyé au client) le résultat, mais il est également possible de récupérer le résultat sous forme de chaîne plutôt que de l'afficher. Le traitement se fait via la méthode parse() de la classe Template.
Exemple :
Code PHP :
//Écrit sur la sortie standard le résultat de l'interprétation du fichier $tpl->parse(); //Renvoie le résultat de l'interprétation du fichier et le place dans $result $result = $tpl->parse(TEMPLATE_STRING_MODE);
Variables simples
Les variables simples permettent de placer du contenu dans un fichier template.
Côté fichier template, il faut placer le nom de la variable entre accolades. Ainsi,
{NOM_DE_LA_VARIABLE}sera remplacé par la valeur de NOM_DE_LA_VARIABLE.
Côté PHP, l'assignation d'une variable se fait via la méthode assign_vars().
L'exemple suivant montre l'utilisation de variables simples.
Fichier template :
L'assignation dans le fichier PHP :
Code PHP :
$tpl->assign_vars(array('HELLO_WORLD' => 'Hello world!'));
Le résultat de l'interprétation donne ceci :
Les boucles
Définition de boucles
Les boucles permettent de répéter une partie de code dans le template. Pour définir une boucle il faut respecter la syntaxe suivante.
Code TPL :
# START boucle # Code répété dans la boucle # END boucle #
Les boucles peuvent être imbriquées. Pour définir une boucle imbriquée il faut respecter la syntaxe suivante.
Code TPL :
# START boucle1 # Code répété dans la boucle 1 # START boucle1.boucle2 # Code répété dans la boucle 2 # END boucle1.boucle2 # # END boucle1 #
Les variables dans les boucles
Les variables dans les boucles doivent être préfixées par la liste des boucles par lesquelles elles ont été assignées, séparées par des points.
Code TPL :
# START boucle1 # Code répété dans la boucle 1 {boucle1.VARBOUCLE_1} # START boucle1.boucle2 # Code répété dans la boucle 2 {boucle1.boucle2.VARBOUCLE_2} Variable de la boucle 1 affichée dans la boucle 2 : {boucle1.VARBOUCLE_1} # END boucle1.boucle2 # # END boucle1 #
L'assignation de boucles
Côté PHP, il faut utiliser la méthode assign_block_vars().
Prenons la boucle simple suivante :
Code TPL :
Je compte jusqu'à 3 # START boucle # Et {boucle.NOMBRE} # END boucle # Et voilà !
L'assignation correspondante sera la suivante :
Code PHP :
for ($i = 1; $i <= 3; $i++) { //On assigne une itération de la boucle 'boucle' avec la variable NOMBRE $tpl->assign_block_vars('boucle', array('NOMBRE', $i)); }
L'interprétation de ce template donnera
Code TXT :
Je compte jusqu'à 3 Et 1 Et 2 Et 3 Et voilà !
Prenons un second exemple avec une boucle imbriquée :
Code TPL :
Classification des sports # START categorie_sport # Catégorie : {categorie_sport.NOM_CATEGORIE} # START categorie_sport.sport # Le {categorie_sport.sport.NOM_SPORT} est un {categorie_sport.NOM_CATEGORIE} # END categorie_sport.sport # # END categorie_sport #
Le code PHP correspondant pourrait être :
Code PHP :
//Sports collectifs $tpl->assign_block_vars('categorie_sport', array('NOM_CATEGORIE' => 'Sport collectif')); //Exemples de sports collectifs $tpl->assign_block_vars('categorie_sport.sport', array('NOM_SPORT' => 'football')); $tpl->assign_block_vars('categorie_sport.sport', array('NOM_SPORT' => 'handball')); $tpl->assign_block_vars('categorie_sport.sport', array('NOM_SPORT' => 'rugby')); //Des sports de glisse $tpl->assign_block_vars('categorie_sport', array('NOM_CATEGORIE' => 'Sport de glisse')); //Exemples de sports de glisse $tpl->assign_block_vars('categorie_sport.sport', array('NOM_SPORT' => 'ski')); $tpl->assign_block_vars('categorie_sport.sport', array('NOM_SPORT' => 'snowboard')); $tpl->assign_block_vars('categorie_sport.sport', array('NOM_SPORT' => 'surf'));
L'exécution de ce code donnerait alors :
Code TEXT :
Classification des sports Catégorie : Sport collectif Le football est un Sport collectif Le handball est un Sport collectif Le rugby est un Sport collectif Catégorie : Sport de glisse Le ski est un Sport de glisse Le snowboard est un Sport de glisse Le surf un Sport de glisse
Les conditions
Bien que les conditions puissent être gérées par des boucles (une boucle assignée 0 ou 1 fois est une condition), il existe également la possibilité de définir des conditions dans les templates. Pour cela, il suffit d'assigner des variables dont les valeurs sont booléennes. Par convention, on les préfixe par C_.
Voici un exemple
Code TPL :
# IF C_HOMME # Vous êtes un homme. # ELSE # Vous êtes une femme. # ENDIF #
Code PHP :
$tpl->assign_vars(array('C_HOMME' => true));
Le code PHP ci-dessus génèrerait
Code TEXT :
Vous êtes un homme.
On peut également faire des variables dans des boucles, en voici un exemple.
Code TPL :
voici une liste de sports # START sport # {sport.NOM} # IF sport.C_COLLECTIF # Attention, ce sport est un sport collectif, il faudra trouver une équipe de {sport.NOMBRE_JOUEURS} pour le pratiquer ! # ENDIF # # END sport #
Code PHP :
//On crée les itérations correspondantes $tpl->assign_block_vars('sport', array( 'NOM' => 'Football', 'C_COLLECTIF' => true, 'NOMBRE_JOUEURS' => 11 )); //Les deux sports suivants ne sont pas collectifs. //On n'est pas obligé de définir la variable NOMBRE_JOUEURS $tpl->assign_block_vars('sport', array( 'NOM' => 'Cyclisme', 'C_COLLECTIF' => false )); $tpl->assign_block_vars('sport', array( 'NOM' => 'Course à pied', 'C_COLLECTIF' => false, 'NOMBRE_JOUEURS' => '' ));
Vous avez compris que l'exemple donnerait :
Code TEXT :
Football Attention, ce sport est un sport collectif, il faudra trouver une équipe de 11 pour le pratiquer ! Cyclisme Course à pied
Les inclusions
Sur PHPBoost 3.1, il est possible d'inclure à un endroit d'un template le résultat de l'interprétation d'un autre template. sur PHPBoost 3.0, c'est aussi possible, mais la façon de le faire est largement dépréciée et nous n'expliquons donc pas comment le faire, il est cependant assez simple de contourner le problème, nous allons le voir dans l'exemple.
Voyons donc cela sur un exemple.
fichier1.tpl :
Code TPL :
Un hello world inclus d'un autre template : # INCLUDE hello_world #
fichier2.tpl :
Code TPL :
Bonjour tout le monde !
Côté PHP, nous avons :
Code PHP :
$tpl1 = new Template('fichier1.tpl'); $tpl2 = new Template('fichier2.tpl'); $tpl1->add_subtemplate('hello_world', $tpl2); //Exécutons le tout ($tpl2 sera également interprété) $tpl1->parse();
Cela donne :
Code TXT :
Un hello world inclus d'un autre template : Bonjour tout le monde !
A noter que c'est strictement équivalent à remplacer
# INCLUDE hello_world #par
{HELLO_WORLD}et à assigner
Code PHP :
$tpl1->assign_vars(array('HELLO_WORLD' => $tpl2->parse(TEMPLATE_STRING_MODE);
Emplacement des templates
Templates des modules
Pour charger un fichier, il faut utiliser le constructeur de la classe Template en utilisant un chemin de la forme suivante : mymodule/file.tpl. Cela aura pour effet de charger le fichier file.tpl de votre module se trouvant dans le dossier /mymodule/templates/.
Mais lors de la création d'un nouveau thème, il est possible qu'un template soit redéfini. Dans ce cas-là, il se trouvera dans /templates/mytheme/modules/mymodule/file.tpl. En fait, si ce dernier existe, il sera choisi en priorité, sinon celui par défaut du module sera utilisé (celui présent dans /mymodule/templates/file.tpl).
Cela a pour effet notamment que l'emplacement du thème change. Si celui-ci utilise des images qui sont également redéfinies, leur chemin ne sera pas le même que dans le thème par défaut. Pour cela, le moteur permet de connaitre où se situent les images. Dans la version 3.0 de PHPBoost, cette information est disponible avec la méthode Template::get_module_data_path(string $module) alors que pour PHPBoost 3.0, une variable template (
{PICTURES_DATA_PATH}) est automatiquement assignée pour cela.
Il est à noter que si une image est redéfinie, elles doivent toutes l'être car la vérification n'est pas faire au cas par cas.
Templates du framework
Il est possible de redéfinir les templates du framework. Pour cela, il suffit de le redéfinir dans le dossier /templates/mytheme/framework/ en recréant l'arborescence depuis là comme par exemple /templates/mytheme/framework/menus/content/display.tpl. Toutes les pages utilisant ce thème utiliseront alors ce template plutôt que celui par défaut (dans le répertoire /templates/default/).
Il est aussi possible de redéfinir le comportement du framework au sein d'un module. Pour cela, il faut redéfinir dans l'arborescence template du module le template en recréant son arborescence. Par exemple /mymodule/templates/framework/menus/content/display.tpl sera utilisé en priorité si il existe. On peut même redéfinir l'utilisation d'un template du framework dans un module pour un thème en le plaçant ici : /templates/mytheme/modules/mymodule/framework/menus/content/display.tpl
En résumé, voici les endroits où le moteur de templates va charger le template (si un il n'est pas trouvé à un emplacement il passe au suivant, jusqu'au dernier qui existe forcément) avec le chargement suivant :
Code PHP :
$tpl = new Template('framework/menus/content/display.tpl');
- /templates/mytheme/modules/mymodule/framework/menus/content/display.tpl
- /mymodule/templates/framework/menus/content/display.tpl
- /templates/mytheme/framework/menus/content/display.tpl
- /templates/default/framework/menus/content/display.tpl (celui-ci existera quoi qu'il arrive)
Il est donc absolument possible de redéfinir l'apparence du framework et son comportement au sein même d'un module sans affecter les autres. Les possibilités de personnalisation du moteur de template permettent de spécialiser modules et thèmes de façon à pouvoir faire ce que l'on souhaite.