Simple Template Engine
Pour un projet un peu plus gros, je cherchais un moteur de templates simple. Je ne voulais pas écrire sans cesse le même code à la fois pour mes scripts côté serveur et côté client, qu'il aurait ensuite fallu modifier laborieusement à deux endroits différents (mot-clé : Single Point Of Maintenance). Un moteur de templates simple (soulignons-le !) ne semble toutefois pas exister pour PHP ou JavaScript, du moins ma recherche a été vaine. L'objectif était donc de transmettre simplement quelques paramètres à un fichier PHP comme à un JavaScript, paramètres qui remplaceraient alors le contenu du template, c'est-à-dire du fichier. Je voulais, lors d'une requête Ajax insérant du contenu dynamique dans la page, utiliser la même « source » de template que pour la construction d'une page avec PHP. Si nous avons par exemple un forum qui affiche des messages (générés par un script PHP) et ajoute aussi des messages dynamiquement via JavaScript (lorsque le message doit s'afficher directement après l'envoi, sans recharger la page), on utiliserait sans ce moteur de templates deux modèles : le template auquel accède le script PHP, et le modèle pour le JavaScript. Désormais, un seul template suffit, utilisé à la fois par PHP et par JavaScript. Les variables sont placées entre accolades, ce qui peut bien sûr être modifié à volonté. Bref, un exemple :
<template source="welcome">
Hallo, mein Name ist {name} und ich bin {age} Jahre alt.
</template>
Ici, nous voulons remplacer {name} et {age} par des variables que nous pouvons transmettre dynamiquement. C'est parti.
Le Javascript
<script language="javascript">
var TemplateEngine = function(tpl, data) {
if ($("template[source='" + tpl + "']").length > 0){
tpl = $("template[source='" + tpl + "']").html();
}else{
$.get(tpl, (data) => tpl = data);
}
var re = /{([^}]+)}/g, match;
while(match = re.exec(tpl)){
tpl = tpl.replace(match[0], data[match[1]]);
}
return tpl;
</script>
Un appel au moteur de templates attend désormais le template (tpl) et les données à transmettre. Comme template, on indique soit la propriété « source » d'un nœud HTML de type « template » à utiliser comme modèle, soit le chemin relatif du fichier qui contient le contenu du template.
TemplateEngine("welcome", {name: 'David', age: 28})
Soit le template figure déjà dans le code source, et alors nous accédons directement à l'élément. Sinon, une requête GET est lancée et le fichier est lu via Ajax. Nous pouvons donc passer comme « tpl » aussi bien un nom de fichier que la valeur de la propriété « source » d'un nœud de type « template ». Le fichier doit alors contenir l'exemple ci-dessus, nœud de template compris. En retour, nous obtenons
Hallo, mein Name ist David und ich bin 28 Jahre alt.
Le PHP
Tout cela doit aussi être possible via PHP, sinon l'ensemble serait relativement absurde ou inutilisable pour l'usage prévu.
class TemplateEngine{
public function compile($file, $data){
preg_match_all('/<template([^>]*)>(.*)<\/template>/m', file_get_contents($file), $content, PREG_SET_ORDER, 0);
$content = $content[0][2];
foreach($data as $key => $value){
$content = str_replace("{".$key."}", $value, $content);
}
return $content;
}
}
On l'appelle simplement ainsi :
$engine = new TemplateEngine();
$engine->compile("myfile.template", ["age" => "28", "name" => "David"]);
Le retour est alors également :
Hallo, mein Name ist David und ich bin 28 Jahre alt.
Ainsi, il suffit désormais de modifier le fichier de template pour obtenir la même sortie côté serveur et côté client !