MOTEUR DE TEMPLATE

coucou747 Messages postés 12303 Date d'inscription mardi 10 février 2004 Statut Membre Dernière intervention 30 juillet 2012 - 24 oct. 2008 à 09:35
webconceptor Messages postés 2 Date d'inscription mercredi 31 mars 2004 Statut Membre Dernière intervention 15 juillet 2009 - 15 juil. 2009 à 16:05
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/48288-moteur-de-template

webconceptor Messages postés 2 Date d'inscription mercredi 31 mars 2004 Statut Membre Dernière intervention 15 juillet 2009
15 juil. 2009 à 16:05
Merci, je veux bien. Je t'envoie mon mail par mp.

Cela dit, j'ai réessayé aussi, et toujours le même problème.
FaustXVI Messages postés 5 Date d'inscription dimanche 11 février 2007 Statut Membre Dernière intervention 15 juillet 2009
15 juil. 2009 à 15:53
Perso je viens de tlécharger l'archive et je n'ai eu aucun probleme. Je te l'envoie par mail si tu veux.
webconceptor Messages postés 2 Date d'inscription mercredi 31 mars 2004 Statut Membre Dernière intervention 15 juillet 2009
7 juil. 2009 à 19:20
Bonjour, bravo pour cet excellent code, mais j'ai voulu récupérer la dernière version et le zip est corrompu... Impossible de décompresser ! Que faire ?
verdy_p Messages postés 202 Date d'inscription vendredi 27 janvier 2006 Statut Membre Dernière intervention 29 janvier 2019
2 nov. 2008 à 19:40
Il n'est pas inutile de rappeler qu'il existe un moteur de template très performant, très utilisé, intégrant la gestion d'un cache et supportant l'édition dynamique des "templates" (ou modèles) pour la génération de code HTML: MediaWiki (ex.: Wikipedia, Wikimedia Commons, Wiktionary, etc. et la plupart des wikis actuels).

Ceci dit un tel code n'est pas inutile pour générer autre chose que du HTML pour un site web; par exemple pour générer du XML tel qu'une image SVG (mais MediaWiki possède de telles extensions permettant de générer toutes sortes de documents à partir de modèles et de données dans une approche de type document-view permettant la séparation du modèle de données et des formulaires ou pages de présentation de ces données.)

On a aussi besoin d'autres templates pour générer des interfaces graphiques XML (par exemple en XUL) ou faire des transformations de données XML, ou manipuler des documents à partir de modèles dynamiques de données et de présentation pour en faire différentes fusions ou l'adaptation aux formats d'entrée de différents outils.

La puissance du moteur de modèles dépend aussi largement de sa puissance expressive, c'est à dire du type de transformation applicable qui doit aller au delà de la simple substitution de variables (par exemple capables d'effectuer du calcul et reourner le résultat de ce calcul et non l'expression elle-même (cf. par exemple {{#expr:...}} dans MediaWiki).

Je n'ai pas tout lu de ton code, je me demande s'il est extensible pour supporter ces extensions expressives, y compris le traitement conditionnel (de type {{#if:}} ou {{#switch:}} en Mediawiki de base), les boucles de longueur variable à condition de terminaison dynamique et la gestion dynamique de variables d'état locales (non supportées dans Mediawiki), ou les fusions multicritères (un domaine où MediaWiki est ectuellement très faible, notammenet pour la catégorisation et l'ajout de métadonnées suivant un nombre indéfini d'axes d'analyse de types différents éventuellement contraints par un schéma de données).
FaustXVI Messages postés 5 Date d'inscription dimanche 11 février 2007 Statut Membre Dernière intervention 15 juillet 2009
30 oct. 2008 à 20:27
@lleriche : absolument pas!
Il te suffit de modifier le code dans index.html afin de mettre ce que tu veux (par exemple un div).
Tu peux meme mettre un bloc dans un autre bloc (ce qui est fait dans l'exemple du zip).
Si tu veux vraiment un autre exemple envoie moi un mail et je t 'en enveraie un.
lleriche Messages postés 1 Date d'inscription vendredi 29 août 2008 Statut Membre Dernière intervention 30 octobre 2008
30 oct. 2008 à 20:05
un exemple d'utilisation ou de pages réalisées avec ?

car si je comprends le résultat d'un bloc sera toujours du type ?
alphanono Messages postés 39 Date d'inscription vendredi 9 mai 2003 Statut Membre Dernière intervention 25 mai 2009
27 oct. 2008 à 15:30
@Kankrelune : Effectivement, je n'y avais pas pensé ... Le cas ne s'était jamais produit pour moi mais je vais intégrer cette notion dans mon code.

Pour ce qui est de la mise en cache ... c'est une question assez épineuse en effet. Je rejoins CodeFalse sur le fait qu'effectivement on fait de la POO alors autant séparer tout ce qui peut l'être mais en même temps, gérer le cache pour une image resizée et gérer le cache d'un template sont deux opérations qui ne se font pas forcement de la même façon. Dans les 2 cas, il faudra génerer un nom de fichier pour le cache d'une façon différente car une image reste la même image où qu'elle soit affichée dans le site. Seul sa taille change. On peut imaginer un fichier de cache : nomimage_taillx_tailley_compression.jpg par exemple. Mais un fichier de template peut être généré de façon différente suivant son contexte d'appel. Alors lui trouver un nom spécifique devient plus complexe. Ensuite, pour une image en cache, on récuperera le lien vers cette image dans le cache. Pour un template en cache, il faudra récupérer l'intérieur du fichier ...
Les possibilités sont tellement différentes que finalement, personnelement, je préfère une gestion du cache des images dans la gestion des images et une gestion du cache des templates dans la gestion des templates ...
codefalse Messages postés 1123 Date d'inscription mardi 8 janvier 2002 Statut Modérateur Dernière intervention 21 avril 2009 1
27 oct. 2008 à 15:12
A la base, PHP est un moteur de template, donc l'utiliser en tant que tel ne pose pas de problème du tout. La principale raison qui fait que certaines personnes sont contre son usage en tant que moteur de template, c'est le fait que le graphiste peux avoir accès à certains éléments et agir en tant que controlleur là ou il ne devrait faire que des conditions ou des boucles, chose qui n'est pas possible avec un moteur de template à part entière.

@Kankrelune : Personnellement je suis partisans du "chaque truc fait une chose mais le fait bien", donc je reste persuadé qu'un système de cache n'a rien à faire dans un moteur de template. Pour pousser aux extrêmes, ce serait comme intégrer tout un site dans un fichier :p
Maintenant c'est très bien que l'on ait pas la même vision de la chose, c'est en partageant nos points de vues que les choses évoluent :)
kankrelune Messages postés 1293 Date d'inscription mardi 9 novembre 2004 Statut Membre Dernière intervention 21 mai 2015
27 oct. 2008 à 14:33
Attention alphanono si la bufferisation de sortie est déja active au moment ou tu récupère le contenu de ton template ça risque de poser problème... il faudrait plutot faire...

if(is_file($_fichierTpl))
{
$oldContents = @ob_get_contents();
if($oldContents === false)
ob_start();
else
ob_clean();

require $_fichierTpl;
$this->template = ob_get_contents();

if($oldContents === false)
ob_end_clean();
else
{
ob_clean();
echo $oldContents;
}
}
else $this->template = "Fichier introuvable : " . $_fichierTpl;

Sinon je rejoins alphanono les conditions, mais surtout les boucles, sont assez utile dans un moteur de template... .. .

@ tchaOo°
alphanono Messages postés 39 Date d'inscription vendredi 9 mai 2003 Statut Membre Dernière intervention 25 mai 2009
27 oct. 2008 à 10:51
lol ... tu comprendras le besoin venu ;)
Mais le MVC n'a rien contre le php dans les templates. Tout dépend de son utilisation. Bien souvent, on utilise même des fichiers (souvent notés en .phtml) qui sont des fichiers de templates représentant des parties html de la page à générer. A l'intérieur de celles-ci, on a des appels vers des méthodes du Modèle qui va interpréter la demande et renvoyer la réponse dans le template.
Par exemple, dans ton Modéle, tu as une gestion d'images.
Dans ta Vue (ton template), tu veux afficher une vignette.
Dans ta vue, tu auras un appel $model->image(fichier,50,50) pour calculer la vignette en 50x50 et la renvoyer à la page. Ce système est bien valide MVC car ces changements de taille des vignettes sont bien liés à la Vue mais calculés par le Modèle.
FaustXVI Messages postés 5 Date d'inscription dimanche 11 février 2007 Statut Membre Dernière intervention 15 juillet 2009
27 oct. 2008 à 09:58
@alphanono : les conditions d'affichages sont plus ou moins gérées étant donnée que si tu ne donne pas la valeur à une variable ou à un bloc, ce dernier ne s'affichera pas. Pour qu'un bloc ne s'affiche pas, il suffit donc de ne pas lui donner de valeur!
Pour ce qui est du php qui s'execute dans le template, c'est contraire au principe du MVC donc je pense que ca n'a ren a faire dans un moteur de template qui est destinée à etre le viewer du site.
alphanono Messages postés 39 Date d'inscription vendredi 9 mai 2003 Statut Membre Dernière intervention 25 mai 2009
27 oct. 2008 à 09:21
Salut, pas mal du tout. Pareil que Codefalse, la gestion des exceptions est amusante ;)

Pour info, une autre façon de traiter la capture du template (celle que j'utilise) dans les grandes lignes :
if(file_exists($_fichierTpl)){
ob_start(); // Démarre la capture dans le buffer
require $_fichierTpl; // Inclue le template. De cette façon, le code php dans le template pourra être exécuté
$this->template = ob_get_contents(); // Récupère le contenu du buffer
ob_end_clean(); // Vide le buffer
} else {
$this->template = "Fichier introuvable : " . $_fichierTpl;
}

Ca peut être utile dans certains cas, ça me permet d'exécuter du code php dans les templates au moment de l'appel.
De plus, cette façon de faire me donne la possibilité d'écrire pendant l'exécution un morceau de template en y plaçant du code php puis de rappeler ce template précalculé pour lui faire exécuter le code php qui lui a été intégré en différé ...
Enfin, y'a plein de possibilités avec cette méthode, même si ce n'est pas ce qu'on utilise le plus fréquemment dans un moteur de template.

Juste une implémentation nécessaire à mon avis : la gestion de conditions. J'utilise fréquemment des conditions qui vont faire qu'un bloc doit s'afficher ou non une fois le template calculé. Avec ma syntaxe :

{?condition?}
mon titre secondaire

{?/condition?}

Et on affecte un Boulean sur la variable condition. A true, il affichera le titre, à false, il n'affichera rien.
kankrelune Messages postés 1293 Date d'inscription mardi 9 novembre 2004 Statut Membre Dernière intervention 21 mai 2015
26 oct. 2008 à 19:26
@ codefalse... je ne suis pas complètement d'accord... sur un projet "simple" ou seul le moteur de template utilise le cache il n'est pas indispensable d'externaliser la gestion du cache car c'est dans ce cas, à mon avis, que ton code s'alourdit pour rien et où tu multiplie les fichiers pour rien... après si d'autres classes sont amenées à utiliser un cache bien entendu dans ce cas la question ne se pose pas mais sinon ça ne me choque pas de laisser à la classe template la gestion de sont propre cache... .. .

"s'il est présent et lisible donc logiquement je ne devrais avoir aucune erreur"

en informatique "je ne devrais pas avoir" !== à "je n'aurais pas" ;o)

@ tchaOo°
FaustXVI Messages postés 5 Date d'inscription dimanche 11 février 2007 Statut Membre Dernière intervention 15 juillet 2009
25 oct. 2008 à 12:30
Bonjour à tous,

déjà merci pour vos remarques!
Je vais faire une mise à jour du code bientôt, j'ai de la famille à la maison ce week-end donc il va falloir être un peux patient :-(!
Pour la doc j'utilise doxygen qui est un system de documentation multi langages donc pas besoin de changer entre le C le C++ le Java (même si la j'utilise Javadoc...) le PHP etc...
J'ai juste une question sur les test à faire après le fopen :
avant d'ouvrir en lecture le fichier, je test s'il est présent et lisible donc logiquement je ne devrais avoir aucune erreur possible sur fopen non??
Arto_8000 Messages postés 1044 Date d'inscription lundi 7 mars 2005 Statut Membre Dernière intervention 13 juillet 2010 7
25 oct. 2008 à 01:53
Très bon comme début pour une classe de template.

Si tu veux pousser plus loin avec cette classe il faudrait que tu puisses tout analyser le template (un peu comme du xml). Une fois que tu as un code analyse et stocké de façon objet, il n'existe plus aucune limite aux features que tu peux y ajouter.
codefalse Messages postés 1123 Date d'inscription mardi 8 janvier 2002 Statut Modérateur Dernière intervention 21 avril 2009 1
24 oct. 2008 à 23:04
@Kankrelune : Pour file_get_contents, j'effectue les tests avant (file_exists && is_readable), et ensuite je test le retour de file_get_contents, donc ca devrait le faire. Après niveau perf, jamais essayé ! :)

Par contre je suis totalement contre l'idée d'intégrer un gestionnaire de cache dans un moteur de template (en règle générale). Beaucoup de tests de templates les évaluents avec un moteur de cache, mais ce n'est pas la règle de base du monde Unix de ne faire qu'UN truc, mais le faire bien ? Un moteur de template, ET, a coté, un moteur de cache.
Je vois absolument pas la liaison entre un moteur de cache et un moteur de template :

$oCache = new MyCache ();
if ($oCache->isInCache ($_SERVER['PHP_SELF'])) // C'est du vite fait, juste pour donner l'idée
echo $oCache->retrieveFromCache ();
else {
$oTpl = new MyTemplate ('MyFile.tpl');
// Traitements
echo $oTpl->render ();
$oCache->save ();
}

Mettre un système de cache dans un moteur de template alourdit le code et ne sert strictement à rien à part transformer le code en un vrai charabiat :p

Bon, après ca c'est mon point de vue, et je sais que beaucoups de gens ne pense pas comme moi, mais je serai intéressé de connaître une bonne raison de mélanger les deux :)

Jte met 7 (pareil, c'est mon interprétation ;) :p)
kankrelune Messages postés 1293 Date d'inscription mardi 9 novembre 2004 Statut Membre Dernière intervention 21 mai 2015
24 oct. 2008 à 18:57
Là je crois qu'on peut m'élire boulet du jour... pour la peine...

//on ouvre le fichier
if(($fichier = @fopen($chemin,'r')) !== false)
{
//on recupere tous le contenu du fichier
$this->_html = @fread($fichier,filesize($chemin));
//on ferme le fichier
@fclose($fichier);

if($this->_html === false)
throw new laPoReussisALireLFichierException;
}
else throw new laPoReussisAOuvrirLFichierException;

@ tchaOo°
kankrelune Messages postés 1293 Date d'inscription mardi 9 novembre 2004 Statut Membre Dernière intervention 21 mai 2015
24 oct. 2008 à 18:52
Zut crotte flute j'ai oublié de noter... au passage utiliser les fonctions f****() c'est bien mais faut les tester aussi si l'ouverture du fichier foire ton fread() risque de pas aimer derrière... .. . ;o)

@ tchaOo°
kankrelune Messages postés 1293 Date d'inscription mardi 9 novembre 2004 Statut Membre Dernière intervention 21 mai 2015
24 oct. 2008 à 18:49
Salut

Pareil j'ai du mal avec les commentaires mais c'est un détail... .. . :o)

Je rejoins les coms précédents sur les notices et les 2 _ à ne surtout pas utiliser le double underscore attention au conventions de nomage... qui plus est toutes tes propriétés étant privées c'est pas utile de les isoler... à la limite le type aurait été plus utile (par ex $sHtml ou $aValeurs)... pareil pour le français anglais... mais bon tout ça ça change pas grand chose au fonctionnement du code... .. . ;o)

@ codefalse : pour le file_get_contents c'est plus court mais moins performant perso j'utilise encore souvent le trio f****() c'est pas pour les 3 lignes que ça prend et au moins tu peux gérer tes erreurs en fonction du moment où ça bloque... ;o)

Sinon dans les grandes lignes (je n'ai pas tout épluché) c'est plutôt bien codé, bien indenté, etc... par contre y a un truc qui me choque

dans ta fonction parse...

# // on recupere toutes les variables
# preg_match_all('/{(.*?)}/',$chaine,$resultat,PREG_SET_ORDER);
#
# //on remplace toutes les variables par leur valeur
# foreach($resultat as $key => $value) {
# //si on a pas de valeur alors on supprime la variable
# if(!isset($valeur[$value[1]])) {$valeur[$value[1]] = '';}
# $chaine = preg_replace('/{'.$value[1].'}/',$valeur[$value[1]],$chaine);
# }

la syntaxe de tes variables est fixe c'est juste une valeur à insérer contrairement à celle d'un block qui définit une portion de code qui sera réutilisé en boucle il est inutile et surtout couteux en perf d'utiliser les regexp ici... un simple...

foreach($resultat as $key => $value)
$chaine = str_replace('{'.$key.'}', $value, $chaine);

(au passage un conseil stock tes délimiteurs de tag dans des propriétées ça sera plus facile à gérer si tu es amené à les modifier... ce qui donnerait str_replace($this->sOpenVar.$key.$this->sCloseVar,...)

pareil pour ton...

$chaine = preg_replace('/\['.$nom[1].'\]/',$resultatparse,$chaine);

str_replace() devrait suffire... .. .

Sinon c'est un détail mais pourquoi tu met entre parenthèse tes fonctions dans tes block de condition... tu alourdis ton code pour rien... .. .

if(!(file_exists($chemin)))

php évalue 2 fois le retour de ta fonction c'est pas utile ici...

if(!file_exists($chemin))

suffit... .. .

Voili voilou ce que j'en pense pas grand chose à dire... il serait intéressant d'y intégrer un petit gestionnaire de cache activable ou non en fonction du template... je met 8/10... .. .

@ tchaOo°
neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
24 oct. 2008 à 14:36
Salut,

J'ai pas bien eu le temps de tout regarder en détails bien que ce genre de source m'intéresse.
Cependant, il y a un truc qui m'a choqué : c'est le constructeur style PHP4.
Bien que ce soit compatible en PHP5, si on étend ta classe, il faut appeler manuellement le constructeur du parent. Or, le constructeur __construct() en PHP5 permet justement de s'affranchir de cette "contrainte"...

Je regarde ça plus en détails ce week end, et je bencherai pour comparer avec le mien :)

En tout cas, ça fait plaisir de voir de temps en temps des sources soignées et documentées.
A propos de la doc... Quel standard respectes-tu ? Pour ma part, je suis habitué à phpDoc (syntaxe identique ou presque à javaDoc, pyDoc), du coup là, ça me perturbe un peu ^^ (mais c'est pas grave...)
codefalse Messages postés 1123 Date d'inscription mardi 8 janvier 2002 Statut Modérateur Dernière intervention 21 avril 2009 1
24 oct. 2008 à 10:06
Salut ! :)

Quelques conseils :
Change ca :
#
# //on ouvre le fichier
# $fichier = fopen($chemin,"r");
#
# //on recupere tous le contenu du fichier
# $this->__html = fread($fichier,filesize($chemin));
#
# //on ferme le fichier
# fclose($fichier);
par un file_get_contents ($chemin); plus court, et ca fait la même chose.

Autre chose, essaye de tenir une convention de nommage. Tu appele tes fonctions en francais :
"$this->trouverBloc($this->__html);" mais tes exceptions (classes) en anglais : "WrongTypeForTemplateException".
Personnellement je préconiserai le tout anglais, mais si tu met tout dans une langue, ce sera déjà bien :)
if($valeurs !null) > remplace le par isset ($valeurs), car avec un error_reporting(E_ALL) tu auras des notices

Tes méthodes magiques get&set ne font pas de vérifications sur l'existence des valeurs (notament la fonction __get, qui retourne la clée demandée, sans chercher à savoir si elle existe). Encore une fois, avec un error_reporting (E_ALL), tu auras des erreurs.

Sinon, c'est un tout petit truc que je vais dire, c'est juste une méthode conseillée, mais tu n'es pas obligé de t'y tenir : tes variables privées commence avec UN seul _ (underscore), afin de différencier les propriétés privées des méthodes/variables/constantes magiques (__get mais private $_maVar);

Bien sûr ce n'est que des conseils, ton code est très bien structuré, de bonnes idées dans la Poo et j'aime bien ta façon de lancer des exceptions :)

J'attends les prochaines mises à jours pour noter :)
coucou747 Messages postés 12303 Date d'inscription mardi 10 février 2004 Statut Membre Dernière intervention 30 juillet 2012 44
24 oct. 2008 à 09:35
salut

super code !

t'as juste une verification d'erreurs a ajouter apres les fopen et choses du genre.
Rejoignez-nous