VI. Virtual Template▲
VI-A. Présentation▲
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é :
if (!
$DEFINE_VTEMPLATE
)
$this
->
varlist=
array_merge($var
[
1
],
$var1
[
1
]
);
$this
->
varlist=
array_merge($this
->
varlist,
$var1
[
1
]
);
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
];
}
if ( $this
->
file_cached[
$handle
][
'
data
'
]
){
Et enfin…
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
"
;
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 :
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 :
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 :
$template
->
setVar($handle
,
'
charset
'
,
$charset
);
<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 :
$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
'
]
);
}
<!--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 :
$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
'
]
);
}
}
}
<!--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 :
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 :
$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 :
$this
->
varlist=
array_merge($var
[
1
],
$var1
[
1
]
);
$this
->
varlist=
array_merge($this
->
varlist,
$var1
[
1
]
);
$all_dir
.=
"
/
$subdir
"
;
//$all_dir.="/$subdir";
return $this
->
path.
$path
.
"
/
$file
"
;
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.