IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Comparatif : Découverte des principaux moteurs de templates en PHP

Smarty, phpBB2, TinyButStrong, VTemplate, ModeliXe
Image non disponible


précédentsommairesuivant

VI. Virtual Template

VI-A. Présentation

Image non disponible

Le projet

VTemplate est un projet français.

Le principe est le même que pour phplib, à savoir utiliser des commentaires HTML dans le gabarit afin de construire un moule de document.

Installation

J'ai utilisé la version 1.3.0 « Cache Edition ».

Avant de commencer, nous allons devoir opérer quelques corrections du code téléchargé :

Trouver :
Sélectionnez
17.
if (!$DEFINE_VTEMPLATE)
Remplacer par :
Sélectionnez
17.
if (!isset($DEFINE_VTEMPLATE))
Trouver :
Sélectionnez
263.
$this->varlist=array_merge($var[1],$var1[1]);
Remplacer par :
Sélectionnez
263.
$this->varlist=array_merge($this->varlist,$var1[1]);
Trouver :
Sélectionnez
377.
378.
379.
380.
381.
382.
   preg_match("(<!--VTP_([^()]+)-->)sU",$code,$reg);

   // Tester la présence des caractères invalides dans le nom ( | et {});
   if (count(explode("|",$reg[1]))>1 || count(explode("{",$reg[1]))>1 || count(explode("}",$reg[1]))>1) exit($this->error(1,$reg[1],1));

   return $reg[1];
Remplacer par :
Sélectionnez
377.
378.
379.
380.
381.
382.
   if (preg_match("/<!--VTP_([^()]+)-->/U",$code,$reg))
   {
       // Tester la présence des caractères invalides dans le nom ( | et {});
       if (count(explode("|",$reg[1]))>1 || count(explode("{",$reg[1]))>1 || count(explode("}",$reg[1]))>1) exit($this->error(1,$reg[1],1));
       return $reg[1];
   }
Trouver :
Sélectionnez
443.
if (count($this->sources[$zone]["fils"])){
Remplacer par :
Sélectionnez
443.
if (!empty($this->sources[$zone]["fils"]) and count($this->sources[$zone]["fils"])){
Trouver :
Sélectionnez
720.
if ( $this->file_cached[$handle]['data'] ){
Remplacer par :
Sélectionnez
720.
if ( !empty($this->file_cached[$handle]['data']) ){

Et enfin…

Trouver :
Sélectionnez
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
    if ( !is_dir($this->path.basename($path."/$file")) ){
    if ( $sub_dir = dirname($path."/$file") ){
      $lsd = explode("/",$sub_dir);
      $all_dir=$this->path;
      foreach($lsd as $subdir){
        //$all_dir.="/$subdir";
        if ( !is_dir($all_dir) ){
          mkdir($all_dir, 0755);
          clearstatcache();
        }
      }
    }
    }
    return $this->path."/$file";
Remplacer par :
Sélectionnez
159.
160.
161.
162.
    if( !is_dir($this->path) ) {
        mkdir($this->path, 0755, TRUE);
    }
    return($this->path.$file);

Arborescence du projet :

  • C:\Web\offline\shared\VTemplate\ : La bibliothèque (VTemplate.php) ;
  • C:\Web\offline\sites\comparatifs\vtemplate\ : La classe personnalisée (MyVTemplate.php) ;
  • C:\Web\online\comparatifs\ : Le script à charger par le navigateur (vtemplate-nocache.php).

Héritage de la classe

Voici la classe que je vous propose d'utiliser :

MyVTemplate.php
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
<?php

require('C:/Web/offline/shared/VTemplate/vtemplate.class.php');

class MyVTemplate extends VTemplate
{
    var $path; // Chemin d'accès au dossier racine commun aux variables suivantes
    var $templates_path; // Chemin d'accès aux templates
    var $caching; // Mise en cache ?
    var $cache_lifetime; // Durée de vie des fichiers de cache (en secondes)

    function MyVTemplate($template, $caching)
    {
        $this->templates_path = dirname($this->path).'/html/';

        if($caching)
        {
            $this->caching = TRUE;
            $this->cache_lifetime = 180;
        }
        else
        {
            $this->caching = FALSE;
        }
    }

    /**
     * MyVTemplate::Open()
     * Surcharge de la méthode Open() pour lui faire accepter un chemin relatif
     *
     * @param string $file
     * @return
     **/
    function Open($file, $useless_1 = NULL, $useless_2 = NULL)
    {
        if($this->caching)
        {
            return parent::Open($this->templates_path.$file, TRUE, $this->cache_lifetime);
        }
        else
        {
            return parent::Open($this->templates_path.$file);
        }
    }
}

?>

Le constructeur attend le nom du gabarit.

Le code suivant permet de créer l'objet dans nos scripts :

vtemplate.php
Sélectionnez
define('DIR_OFFLINE', 'C:/Web/offline/sites/comparatifs/vtemplate/');
define('VTP_TEMPLATE', 'default');

require(DIR_OFFLINE.'MyVTemplate.php');

$template = new MyVTemplate(VTP_TEMPLATE);

//
// Série d'appels à $template->Open() et $template->Display() espacés d'envois de données au gabarit
//

VI-B. Utilisation

Variables

La méthode setVar() remplit cet office :

header.php
Sélectionnez
$template->setVar($handle, 'charset', $charset);
header.tpl
Sélectionnez
<meta http-equiv="Content-Type" content="text/html; charset={#charset}" />

Blocs

Pour répéter une portion du gabarit, Virtual Template utilise ce qu'il appelle une session :

home.php
Sélectionnez
$sql = 'SELECT id, title
        FROM subject';
$subjects = mysql_query($sql) or die(mysql_error());
while($subject = mysql_fetch_assoc($subjects))
{
    $template->newSession($handle, 'subject');
    $template->setVar($handle, 'subject.title', $subject['title']);
}
home.tpl
Sélectionnez
<!--VTP_subject-->
    <div class="bloc_cours">
        <div class="titre_cours">{#title}</div>
    </div>
    <br />
    <br />
<!--/VTP_subject-->

Dans la version téléchargée pour la rédaction de ce comparatif, la méthode newSession() appelait la méthode addSession() avec trois paramètres de trop. C'est pour cela que j'ai proposé ci-dessus un correctif. Une solution alternative serait d'appeler addSession() puis closeSession().

Imbrication

VTemplate permet d'imbriquer les boucles les unes dans les autres de cette manière :

home.php
Sélectionnez
$sql = 'SELECT id, title
        FROM subject';
$subjects = mysql_query($sql) or die(mysql_error());
while($subject = mysql_fetch_assoc($subjects))
{
    $template->newSession($handle_home, 'subject');
    $template->setVar($handle_home, 'subject.title', $subject['title']);

    $sql = 'SELECT id, title
            FROM category
            WHERE subject_id = '.$subject['id'];
    $categories = mysql_query($sql) or die(mysql_error());
    while($category = mysql_fetch_assoc($categories))
    {
        $template->newSession($handle_home, 'category');
        $template->setVar($handle_home, 'category.title', $category['title']);

        $sql = 'SELECT id, uri, title, description
                FROM tutorial
                WHERE category_id = '.$category['id'];
        $tutorials = mysql_query($sql) or die(mysql_error());
        while($tutorial = mysql_fetch_assoc($tutorials))
        {
            $template->newSession($handle_home, 'tutorial');
            $template->setVar($handle_home, 'tutorial.uri', $tutorial['uri']);
            $template->setVar($handle_home, 'tutorial.title', $tutorial['title']);
            $template->setVar($handle_home, 'tutorial.description', $tutorial['description']);
        }
    }
}
home.tpl
Sélectionnez
<!--VTP_subject-->
    <div class="bloc_cours">
        <div class="titre_cours">{#title}</div>
    <!--VTP_category-->
        <div class="categorie_cours">{#title}</div>
        <div class="liste_cours">
            <ul>
        <!--VTP_tutorial-->
                <li>
                    <a href="{#uri}">{#title}</a> : {#description}
                </li>
        <!--/VTP_tutorial-->
            </ul>
        </div>
        <hr />
    <!--/VTP_category-->
    </div>
    <br />
    <br />
<!--/VTP_subject-->

Il est impossible d'appeler une variable d'une session parente, par exemple le titre d'un sujet dans la session d'un tutoriel. À moins, bien sûr, de dupliquer cette variable dans le gabarit.

Alternance

VTemplate ne propose pas de moyen interne permettant d'alterner les couleurs de lignes, il faut donc avoir recours au subterfuge habituel :

home.php
Sélectionnez
            if($i % 2)
            {
                $style = 'green';
            }
            else
            {
                $style = 'blue';
            }

            $template->setVar($handle, 'tutorial.style', $style);
home.tpl
Sélectionnez
        <!--VTP_tutorial-->
                <li>
                    <a href="{#uri}">{#title}</a> : <span style="color: {#style};">{#description}</span>
                </li>
        <!--/VTP_tutorial-->

Segmentation du gabarit

Avec VTemplate, chaque gabarit est chargé dans un handle qu'il est possible de manipuler indépendamment.

Pour segmenter la page avec différents gabarits, il faut procéder ainsi :

vtemplate.php
Sélectionnez
$template = new MyVTemplate(VTP_TEMPLATE);

// Déclaration des handles
$handle_header = $template->Open('header.tpl');
$handle_home = $template->Open('home.tpl');
$handle_footer = $template->Open('footer.tpl');

//
// À mettre ici : envoi des informations aux handles
//

// Affichage des handles
$template->Display($handle_header);
$template->Display($handle_home);
$template->Display($handle_footer);

Gestion du cache

La gestion du cache se fait au moyen d'une classe VTemplate différente de la version normale.

Dans la classe disponible au moment de la rédaction de cet article (1.3 Cache Édition de mars 2002), il m'a fallu corriger une variable de la ligne 263 :

Trouver dans la méthode Session::parseVar() :
Sélectionnez
$this->varlist=array_merge($var[1],$var1[1]);
Ligne corrigée :
Sélectionnez
$this->varlist=array_merge($this->varlist,$var1[1]);
Trouver dans la méthode Cache::getFileName() :
Sélectionnez
$all_dir.="/$subdir";
Ligne corrigée :
Sélectionnez
//$all_dir.="/$subdir";
Trouver dans la méthode Cache::getFileName() :
Sélectionnez
return $this->path.$path."/$file";
Ligne corrigée :
Sélectionnez
return $this->path."/$file";

Avec ces modifications, les fichiers de cache sont créés dans le système de fichiers. Il semble rester des erreurs à d'autres endroits, mais j'avoue ne plus avoir envie de déboguer…

VI-C. Mon avis

Avantages

Inconvénients

J'ai cru lire que VTemplate 1.3.3 était écrit en PHP 5, j'ai dû faire erreur. Il s'agit plutôt d'une classe PHP 4 compatible PHP 5 (comme toutes les classes PHP 4, en fait). Je préfère ne pas savoir quelles modifications ont été apportées pour valider cette compatibilité…

Les méthodes retournent -1 en cas d'erreur. Ce n'est pas une valeur assimilable à FALSE… Impossible d'utiliser la négation if(!open()) ou la comparaison booléenne if(open() === FALSE). De plus, aucune constante n'est définie avec la valeur -1. Par conséquent, la sémantique de la gestion d'erreurs est inexistante, ce qui rend le code difficile à lire.

Le changement entre la version « sans mise en cache » et la version « avec mise en cache » est complexe et peu flexible : il faut télécharger des scripts différents, mais au nom identique depuis le site officiel. Il est possible d'utiliser en permanence la version avec gestion du cache, mais au prix d'un numéro de version (1.3.0 au lieu de 1.3.3 pour la version sans mise en cache).

Les classes utilisées par VTemplate ont des noms génériques (« Err » et « Session »), ce qui a de fortes chances de poser des collisions lors de l'intégration au projet.

La configuration se fait au moyen de constantes situées dans le scope global. Il est notamment possible de modifier le tag d'ouverture des variables du gabarit, mais pas le tag de fermeture. Des noms de constantes comme « VTP_ALL » et « VTP_CACHED » auraient été plus heureux et il aurait été encore plus adapté de les placer à l'intérieur d'une classe écrite en PHP 5, ce qui donnerait des noms comme « VTemplate::ALL » et « VTemplate::CACHED ». Enfin, le répertoire des fichiers de cache n'est pas configurable par gabarit.

Conclusion

Il m'a été difficile d'utiliser VTemplate, car je m'attendais à une classe prête à l'utilisation, or j'ai été contraint de lire son code pour la déboguer. Les bugs sont nombreux, c'est assez déplaisant.

Je n'ai généralement ni l'envie ni le temps de déboguer une classe avant de pouvoir l'utiliser, VTemplate n'a donc pas ma préférence.

Si quelqu'un a vécu une expérience différente, qu'il n'hésite pas à me le faire savoir. C'est surtout dommage pour la gestion du cache, car, au vu de la rapidité du moteur selon mes tests, je m'attendais à quelque chose d'impressionnant.

Un résumé est disponible en fin d'article.


précédentsommairesuivant

Copyright © 2006 Guillaume Rossolini. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.