comprendre les bases d'un framework en PHP
V. Moteur de template
V-A. Introduction
V-B. Chargement du fichier
V-C. Fonction affiche
V-D. Conclusion
V. Moteur de template
V-A. Introduction
Bien que nous ayons vu brièvement une définition de ce qu'est
un moteur de template, il peut être sage de s'y arrêter un moment :
Leur utilisation divise le monde informatique : certains
crient a l'hérésie, a la perte de performance... Si le sujet
vous intéresse vous pouvez lire un article
ici
ou bien
la
Si ces pages n'existent plus, une simple recherche google,
comme toujours, vous permettra de trouver de nombreux fils
de discussion a ce sujet, et de, pourquoi pas, vous faire
votre propre idée.
Une dernière mise en garde : les moteur de template sont
décriés, entre autre, car ils entraînent une baisse de
performance, en cas, je peut vous assurer que celui que vous
allez voir n'est en aucuns cas optimisé, il n'a aucune autre
prétention que d'être un outil didactique. Si vous décidez
de l'utiliser, vous en avez bien sur le droit, mais c'est a
vos risques et périls (comme pour tout le reste du programme ;p )
V-B. Chargement du fichier
La première fonction est loin d'être la plus complexe : nous
allons tout simplement ouvrir le fichier HTML contenant le template.
| fonction chargeTemplate() | function chargeTemplate($fichier) {
//on ouvre le fichier, et on affiche pas d'erreure si elle arrive : renvoyer null suffit!
if (! $file = @file_get_contents($fichier)) {
$file = null;
}
$file = ouvreSousFichiers($file);
return $file;
} |
Seule une fonction doit vous poser problème :
ouvreSousFichiers() : nous allons voir tout de suite
son code :
| fonction ouvreSousFichiers() | function ouvreSousFichiers(&$template) {
//definnition du motif de recherche :
$motif = "\[ *fileOpen *; *([[:alnum:]_/]*) *\]"; //ex : "[ fileOpen; toto]"
while ( eregi($motif, $template, $balises)) {
//on stocke la balise pour la remplacer plus tard
$balise = $balises[0];
$nomFichier = "templates/" . $balises[1] . ".html";
if (! $file = @file_get_contents($nomFichier) ) {
dbgStore("Erreure, le fichier a inserer dans le template n'a pas put etre ouvert : "
. $nomFichier, TEMPLATE);
return $template;
}
$template = str_replace($balise, $file, $template) ;
}
return $template;
} |
Ici, ça commence a se corser! Mais accrochez vous, tout le
reste du code va se voir truffé de ce mystérieux
eregi
Et toute la difficulté consiste a comprendre la signification
de la chaîne qui lui est passée en paramètre :
"\[ *fileOpen *; *([[:alnum:]_/]*) *\]"; //ex : "[ var; toto]"
cette chaîne est une
expression régulière POSIX
Les expressions régulières sont un langages a elles seules,
elles servent a codifier de façon très puissante une chaîne
de caractère a rechercher, de nombreux tutoriaux sont disponibles
a leur sujet, en voici quelques uns :
- document très clair de cyberzoïde :
lien
- définition du dico des développeurs : lien
- un document de l'l'université de creteil : lien
De nombreuses autres sources existent, cependant, le premier
lien fournit devrait être suffisant, si vous le lisez avec
attention. Nous n'allons pas nous attarder sur ce domaine,
sachez juste que :
- "/[" : est un échappement du caractère "[" qui a une signification particulière
- "*" : signifie que le caractère précédent doit être présent de 0 a n fois
- "[]" : indique une liste, tout caractère présent dans cette liste est acceptable, de plus, les crochets peuvent êtres imbriqués.
- "[:alnum:]" : est un alias pour alpha numérique ce qui signifie, bien entendu que tout caractère alpha numérique doit être accepté,
- "[[:alnum:]_/]*" : signifie donc "de 0 a n fois peuvent être présent : a-zA-Z0-9_/"
Ainsi, le programme agit de la sorte :
tant q'une balise correspondant a l'expression régulière est trouvée,
on ouvre le fichier HTML correspondant, et on remplace (cf : str_replace()
) la balise par le fichier ouvert.
Passons a la fonction suivante :
V-C. Fonction affiche
Cette fonction est la dernière du moteur appelée, au cours
de l'exécution, d'autres fonction vont être exécutées,
cependant, au vue de leur complexité, mieux vaut les voir en
dernier.
Le principe de cette fonction est très simple :
elle va effectuer une substitution des balises de type :
[var;nomDeVariable]
avec nomDeVariable qui est un nom de variable globale de PHP.
Ensuite, un simple echo va permettre d'afficher le template
sur la sortie standard (l'envoyer au client) :
| focntion affiche | function affiche(&$template) {
//definition du motif des balises fixes
$motif = "\[ *var *; *([[:alnum:]_]*) *\]"; //ex : "[ var; toto]"
//on charge les balises dans le tableau balises
while ( eregi($motif, $template, $balises)) {
//on stocke la balise pour la remplacer plus tard
$balise = $balises[0];
$variable = $balises[1];
if (isset($GLOBALS[$variable])) {
dbgStore("On va substituer $balise par {$variable} qui possede la valeur : {$GLOBALS[$variable]}",
TEMPLATE);
$template = str_replace($balise, $GLOBALS[$variable], $template)
or die("erreure lors de l'insertion du substitu : non trouvé");
} else {
dbgStore("La variable globale '$variable' n'a pas ete trouvée..." .
" On la remplace par ''", TEMPLATE);
$template = str_replace($balise, "", $template)
or die("erreure lors de l'insertion du substitu : non trouvé");
}
}
//on envoie le template sur la sortie standard
echo $template;
} |
plus qu'une fonction, et vous retrouvez votre liberté! Mais
attention, c'est une fonction championne! Si vous avez eu du
mal a comprendre les codes précédents accrochez vous!
Afin de faciliter votre travail, nous allons l'étudier pas a pas.
Tout d'abord, son but : remplacer une série de "blocs"
situés dans le template HTML par le résultat d'une requête
au serveur MySQL.
le "bloc" se présentera ainsi :
| exemple d'un bloc a substituer | <ul>
<li>
[bloc1;block = li]
nom : [bloc1; nom], <br />
prénom : [bloc1; prenom ] ,<br />
adresse : [ bloc1 ;adresse]
</li>
</ul> |
ce code est composé de deux types de balises :
le premier type définit quelle est l'étendue du code HTML a
répéter : ici le tag "li"
le second informe le programme sur la colonne (du résultat
de la requête SQL) qui doit remplacer notre balise.
Etudions le code qui permet de trouver le code HTML a dupliquer :
| function mergeDyn($indexBalise, $resultQuery) {
global $template;
dbgStore("on est dans MergeDyn", TEMPLATEDYN);
$motifBaliseBlock = "\[ *$indexBalise *; *block *= *([[:alnum:]]+) *\]";
//ex : "[ balise1; block= toto]"
eregi($motifBaliseBlock, $template, $blockNom);
$baliseMere = $blockNom[0]; //recuperation de la balise correspondante trouvée
$blockNom = ($blockNom[1]);
$blockDebut = "<" . $blockNom . ">";
$blockFin = str_replace("<", "<\/", $blockDebut);
dbgStore("Balise mere : '$baliseMere'", TEMPLATEDYN); |
la variable $motifBaliseBlock contient la chaîne de
recherche, elle est du type : "[ $indexBalise; block = blocHTML]"
$indexBalise est une variable passée en paramètre.
La fonction eregi retourne un tableau, dont :
le premier élément est la balise trouvée (dans notre exemple,
ce serait [bloc1;block = li])
le second élément est le tag HTML correspondant a la portée du bloc
(dans notre exemple : "li")
celui ci est fournit par eregi grâce aux parenthèses
entourant ([[:alnum:]]+) qui spécifient que cet élément
doit aussi être retourné individuellement.
A partir de ces données, le programme renseigne les variables
$blockDebut et $blockFin.
la fonction continue en effectuant ce traitement :
| trouver tout le bloc HTML | //extraction du block defini dans la balise extraite
$motifBlock = "/$blockDebut(.(?<!$blockDebut))*\[ *$indexBalise *; *block *= *$blockNom *\]
.*$blockFin/sU";
//ex : "<li>.\[ *testBDD *; *block *= *([[:alnum:]]+)* *]\].</li>"
dbgStore("Motif de recherche du block : $motifBlock", TEMPLATEDYN);
preg_match($motifBlock, $template, $block);
$block = $block[0];
dbgStore("Bloc de travail : $block", TEMPLATEDYN); |
Le bloc HTML global (celui de notre exemple) est trouvé a partir
des données trouvées plus haut.
la séquence :
$blockDebut(.(?<!$blockDebut))*
signifie : "trouver le dernier bloc de début (ici <li>)
avant la suite du motif.
Un exemple peut être plus parlant :
| exemple | <ul>
<li>
texte a ne pas prendre en compte
</li>
<li>
[bloc1; block = li]
...
</li>
</ul> |
Dans cet exemple, si nous n'avions pas mis
$blockDebut(.(?<!$blockDebut))*
le "texte a ne pas prendre en compte" aurait été compris dans le motif...
Une fois le motif créé, la fonction preg_match()
s'occupe de récupérer le bloc HTML entier allant de <li> a </li>.
la variable $block contient ce bloc.
ensuite, cette série d'instruction est suivie :
| remplacement des secondes balises | //recherche de toutes les sous balises, et remplacement par leur equivalent BDD
$motifSousBalises = "/\[ *$indexBalise *; *([[:alnum:]_]+) *\]/";
preg_match_all($motifSousBalises, $block, $SousBalises, PREG_SET_ORDER);
$mergedBlock = "";
//interrogation de la base, a partir de la ressource recue en parametre
while ($row = mysql_fetch_array($resultQuery, MYSQL_BOTH ) ) {
//boucle de duplication par les valeur BDD
$blockEntraitement = $block;
foreach ($SousBalises as $SousBalise) {
$blockEntraitement = str_replace($SousBalise[0],$row[$SousBalise[1]],
$blockEntraitement);
}
$mergedBlock .= $blockEntraitement;
} |
De nombreux traitements s'enchaînent ici :
Dorénavant, vous devez être habitués aux expressions régulières
ainsi, le début ne doit pas vous poser de problème :
définition du motif des sous blocs, puis leur recherche. Le tableau
$SousBalises contiendras toutes les occurrences trouvées.
Ensuite, la base de donnée est interrogée a l'aide d'une
ressource de requête passée en paramètre.
Tant qu'il existe des réponse de la part de la base non lues,
chaque sous balise est passée en revue et est remplacé par la colonne correspondante :
tout comme précédemment,
"/\[ *$indexBalise *; *([[:alnum:]_]+) *\]/"
comporte une parenthèse permettant d'isoler la chaîne située
après le ";" (ex : dans [bloc1; nom], la chaîne "nom"
sera isolée et remplacée par une colonne de la requête s'appelant
"nom".
au fur et a mesure, $mergedBlock se voit remplit des résultats
de la base, tout en gardant la mise en forme originale (tags
<li>...).
V-D. Conclusion
Voila, notre programme est terminé, il est apte a accueillit
un site en PHP, et d'offrir a son auteur un support de tous
les concepts évoqués plus haut.
Les sources présentés sur cette pages sont libre de droits,
et vous pouvez les utiliser à votre convenance. Par contre cette page de présentation de ces sources constitue une oeuvre intellectuelle protégée par les droits d'auteurs. Copyright ©2006 .
Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu :
textes, documents, images, etc sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages et intérets.
.
|