III. phpBB2 (PHP Base Library - phplib)▲
III-A. Présentation▲
|
|
Les projets▲
PHP Base LibraryLe site officiel de la phplib est l'une des premières bibliothèques permettant d'utiliser un système de gabarits.
L'idée de la phplib est d'utiliser des fichiers de gabarit (l'extension classique est « .ihtml ») qui contiennent le code HTML utilisé. Ces gabarits sont de véritables patrons, ils définissent uniquement une structure ou des éléments de structure. C'est un moule qui ne comporte aucun élément de logique.
phpBB2Site officiel de phpBB2 est un script de forum très populaire.
Il y a de cela plusieurs années, le phpBB Group a effectué un très gros travail autour du template de la PHPLib afin de le rendre plus performant. C'est la version phpBB2 (dont le script de forum est actuellement en bêta) que je vais utiliser ici, plutôt que la version PHPLib qui manque de maturité. L'extension de fichier est « .tpl ».
Installation▲
Extraire le script offline/template.php de l'archive de la dernière version de phpBB2, puis le déplacer dans un répertoire accessible par les utilisateurs du serveur (mais situé hors de la racine du serveur Web). La classe utilise ne fonction globale de phpBB, il faut donc s'en défaire : remplacez « phpbb_realpath » par « realpath ».
Arborescence du projet :
- C:\Web\offline\shared\phpBB2\ : La bibliothèque (template.php) ;
- C:\Web\offline\comparatifs\phpbb2\ : La classe personnalisée (MyTemplate.php) ;
- C:\Web\online\comparatifs\ : Le script à charger par le navigateur (phpbb2.php)
Héritage de la classe▲
Pour reprendre la méthode utilisée avec Smarty, je vous propose de déclarer notre propre classe qui étend Template en la configurant selon nos besoins. Dans cette démonstration, nous n'aurons pas besoin de certaines possibilités offertes par Template, nous pouvons donc simplifier les appels aux méthodes set_filenames() et pparse(). De plus, nous allons ajouter une méthode pour simplifier la conversion du texte en entités HTML.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
<?php
require('C:/Web/offline/shared/phpBB2/template.php'
);
class
MyTemplate extends
Template
{
function
MyTemplate($template_name
)
{
$basedir
=
str_replace('\
\'
, '
/
', dirname(__FILE__))
.'
/
templates/
'.$template_name;
$this->set_rootDir($basedir);
}
function getHtml($string)
{
return htmlentities($string, ENT_QUOTES, '
ISO-
8859
-
1
');
}
}
?>
Le constructeur attend uniquement le nom du fichier de gabarit.
Le code suivant permet de créer l'objet dans nos scripts :
define('
DIR_OFFLINE
'
,
'
C:/Web/offline/comparatifs/phpbb2/
'
);
define('
PHPBB2_TEMPLATE
'
,
'
default
'
);
require(DIR_OFFLINE.
'
MyTemplate.php
'
);
$template
=
new MyTemplate(PHPBB2_TEMPLATE);
//
// Série d'appels à $template->set_filenames() suivis d'envois de données et de $template->pparse()
//
III-B. Utilisation▲
Le moteur utilise des commentaires HTML pour faire la liaison entre PHP et les blocs à reproduire. Les variables sont encadrées par des accolades, ce qui ne nous dépayse pas des autres moteurs du marché.
Pour utiliser le gabarit, il faut commencer par dire quel fichier de gabarit nous souhaitons utiliser. Cela se fait au moyen de la méthode set_filenames() :
$template
->
set_filenames(array('
header
'
=>
'
header.tpl
'
));
// Mettre ici l'envoi des données au gabarit
$template
->
pparse('
header
'
);
Cette méthode recherche un fichier de gabarit du même nom que le script PHP l'appelant (mais avec une extension .tpl au lieu de .php).
Variables▲
L'envoi de variables au fichier de gabarit se fait généralement à l'aide de la méthode assign_vars(). Par convention, les noms des variables du gabarit s'écrivent en majuscules :
$template
->
assign_vars(
array
(
'
CHARSET
'
=>
$template
->
getHtml($header
[
'
charset
'
]
),
'
META_GENERATOR
'
=>
$template
->
getHtml($meta
[
'
generator
'
]
),
'
META_DESCRIPTION
'
=>
$template
->
getHtml($meta
[
'
description
'
]
),
'
META_KEYWORDS
'
=>
$template
->
getHtml($meta
[
'
keywords
'
]
),
'
META_MSLOCALE
'
=>
$template
->
getHtml($meta
[
'
mslocale
'
]
),
'
CSS_MAINSTYLE
'
=>
$template
->
getHtml($css
[
'
mainstyle
'
]
),
'
CSS_PRINTER
'
=>
$template
->
getHtml($css
[
'
printer
'
]
),
'
CSS_RIDAN
'
=>
$template
->
getHtml($css
[
'
ridan
'
]
),
'
TITLE
'
=>
$template
->
getHtml($header
[
'
title
'
]
)
)
);
Du côté du gabarit, voici comment cela se traduit :
...
<head>
<title>{TITLE}</title>
<meta http-equiv
=
"Content-Type"
content
=
"text/html; charset={CHARSET}"
/>
<meta name
=
"generator"
content
=
"{META_GENERATOR}"
/>
<meta name
=
"description"
content
=
"{META_DESCRIPTION}"
/>
<meta name
=
"keywords"
content
=
"{META_KEYWORDS}"
/>
<meta name
=
"MS.LOCALE"
content
=
"{META_MSLOCALE}"
/>
<link rel
=
"stylesheet"
type
=
"text/css"
href
=
"{CSS_MAINSTYLE}"
/>
<link rel
=
"stylesheet"
type
=
"text/css"
media
=
"print"
href
=
"{CSS_PRINTER}"
/>
<link rel
=
"stylesheet"
type
=
"text/css"
media
=
"screen"
href
=
"{CSS_RIDAN}"
/>
</head>
...
C'est une syntaxe plus pénible à écrire que dans le cas de Smarty. En contrepartie, nous avons davantage le contrôle sur ce qu'il se passe. Nous ne sommes pas contraints de préparer toutes les données à l'avance, nous pouvons les envoyer au fur et à mesure (même si ce n'est pas conseillé).
Blocs▲
Les blocs sont des portions du gabarit que l'on peut ignorer, afficher ou bien dupliquer comme on le souhaite. Par convention, les noms des blocs sont écrits en minuscules et les blocs conditionnels (affiché/caché) sont préfixés de « switch_ ».
Ici, nous n'utiliserons pas de bloc conditionnel.
L'affectation d'un bloc se fait au moyen de la méthode assign_block_vars() dans le code PHP :
foreach($subjects
as $subject
)
{
$template
->
assign_block_vars
(
'
subject
'
,
// le nom du bloc
array('
TITLE
'
=>
$template
->
getHtml($subject
[
'
title
'
]
)) // le contenu
);
}
Dans le gabarit, on retrouve le même nom de bloc dans un commentaire HTML. Un commentaire BEGIN et un autre END permettent de délimiter notre bloc. La notation pointée permet d'accéder aux variables :
<!-- BEGIN subject -->
<div class
=
"bloc_cours"
>
<div class
=
"titre_cours"
>
{subject.TITLE}</div>
</div>
<br />
<br />
<!-- END subject -->
Il est possible d'accéder à une variable de niveau supérieur : c'est ce qui justifie la présence du nom de bloc devant le nom de la variable.
Imbrication▲
Le moteur de gabarit de phpBB2 permet d'imbriquer les blocs de la manière suivante :
$sql
=
'
SELECT id, title
FROM subject
'
;
$result
=
mysql_query($sql
) or die(mysql_error());
while($subject
=
mysql_fetch_assoc($result
))
{
$template
->
assign_block_vars
(
'
subject
'
,
array('
TITLE
'
=>
$template
->
getHtml($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
->
assign_block_vars
(
'
subject.category
'
,
array('
TITLE
'
=>
$template
->
getHtml($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
->
assign_block_vars
(
'
subject.category.tutorial
'
,
array
(
'
URI
'
=>
$template
->
getHtml($tutorial
[
'
uri
'
]
),
'
TITLE
'
=>
$template
->
getHtml($tutorial
[
'
title
'
]
),
'
DESCRIPTION
'
=>
$template
->
getHtml($tutorial
[
'
description
'
]
)
)
);
}
}
}
<!-- BEGIN subject -->
<div class
=
"bloc_cours"
>
<div class
=
"titre_cours"
>
{subject.TITLE}</div>
<!-- BEGIN category -->
<div class
=
"categorie_cours"
>
{subject.category.TITLE}</div>
<div class
=
"liste_cours"
>
<ul>
<!-- BEGIN tutorial -->
<li>
<a href
=
"{subject.category.tutorial.URI}"
>{subject.category.tutorial.TITLE}</a>
:
{subject.category.tutorial.DESCRIPTION}
</li>
<!-- END tutorial -->
</ul>
</div>
<hr />
<!-- END category -->
</div>
<br />
<br />
<!-- END subject -->
Alternance▲
Avec le moteur de phpBB2, tout ce qui est « logique » est conservé dans le code PHP, fut-ce un test conditionnel. Ce qui se trouve dans le gabarit n'est rien de plus qu'un moule. Par conséquent, les alternances sont plus complexes à gérer qu'avec Smarty.
Il existe cependant une méthode pour arriver à un résultat similaire :
foreach($category
[
'
tutorials
'
]
as $i
=>
$tutorial
)
{
$template
->
assign_block_vars
(
'
subject.category.tutorial
'
,
array
(
'
URI
'
=>
$template
->
getHtml($tutorial
[
'
uri
'
]
),
'
TITLE
'
=>
$template
->
getHtml($tutorial
[
'
title
'
]
),
'
DESCRIPTION
'
=>
$template
->
getHtml($tutorial
[
'
description
'
]
)
)
);
if($i
%
2
)
{
$template
->
assign_block_vars('
subject.category.tutorial.switch_odd
'
,
array());
}
else
{
$template
->
assign_block_vars('
subject.category.tutorial.switch_even
'
,
array());
}
}
<!-- BEGIN tutorial -->
<li>
<a href
=
"{subject.category.tutorial.URI}"
>{subject.category.tutorial.TITLE}</a>
:
<!-- BEGIN switch_even -->
<span style
=
"color: blue;"
>
{subject.category.tutorial.DESCRIPTION}</span>
<!-- END switch_even -->
<!-- BEGIN switch_odd -->
<span style
=
"color: green;"
>
{subject.category.tutorial.DESCRIPTION}</span>
<!-- END switch_odd -->
</li>
<!-- END tutorial -->
Notez comme la variable DESCRIPTION du bloc subject.category.tutorial est affichée dans les blocs subject.category.tutorial.switch_even et son confrère sans que cela pose de souci.
Une autre méthode utilise une variable :
foreach($category
[
'
tutorials
'
]
as $i
=>
$tutorial
)
{
if($i
%
2
)
{
$style
=
'
green
'
;
}
else
{
$style
=
'
blue
'
;
}
$template
->
assign_block_vars
(
'
subject.category.tutorial
'
,
array
(
'
URI
'
=>
$template
->
getHtml($tutorial
[
'
uri
'
]
),
'
TITLE
'
=>
$template
->
getHtml($tutorial
[
'
title
'
]
),
'
DESCRIPTION
'
=>
$template
->
getHtml($tutorial
[
'
description
'
]
),
'
STYLE
'
=>
$style
)
);
}
<!-- BEGIN tutorial -->
<li>
<a href
=
"{subject.category.tutorial.URI}"
>{subject.category.tutorial.TITLE}</a>
:
<span style
=
"color: {subject.category.tutorial.STYLE};"
>
{subject.category.tutorial.DESCRIPTION}</span>
</li>
<!-- END tutorial -->
Cette version est plus lisible, mais elle a l'inconvénient de contenir une valeur CSS dans le code PHP. En général, c'est quelque chose que nous aimerions éviter.
Segmentation du gabarit▲
Le moteur de phpBB2 permet d'inclure plusieurs fichiers de gabarit dans un seul objet Template. Il n'est pas nécessaire d'appeler la méthode pparse() pour un handle spécifique, ce qui permet une gestion souple comme par exemple envoyer le contenu d'un gabarit dans une variable d'un autre gabarit.
Dans le cas qui nous occupe ici, seule la segmentation nous intéresse : le moyen d'avoir des gabarits externes que l'on peut inclure au gabarit de la page actuelle.
Chaque gabarit chargé au moyen de la méthode set_filenames() étant indépendant grâce à son handle unique, nous pouvons charger plusieurs fichiers de gabarit en une fois :
$template
=
new MyTemplate(PHPBB2_TEMPLATE);
// Déclaration des gabarits utilisés + affectation à des handles
// Note : il est possible d'appeler set_filenames() à plusieurs reprises
$template
->
set_filenames(array(
'
header
'
=>
'
header.tpl
'
,
'
home
'
=>
'
home.tpl
'
,
'
footer
'
=>
'
footer.tpl
'
));
//
// À mettre ici : envoi des données au handle "header"
//
// Affichage du handle "header"
$template
->
pparse('
header
'
);
//
// À mettre ici : envoi des données au handle "home"
//
// Affichage du handle "home"
$template
->
pparse('
home
'
);
//
// À mettre ici : envoi des données au handle "footer"
//
// Affichage du handle "footer"
$template
->
pparse('
footer
'
);
III-C. Mon avis▲
Avantages▲
Ce moteur utilise PHP et les commentaires HTML, ce qui le rend très facile d'accès (car le développeur et le graphiste n'ont pas besoin d'apprendre un nouveau langage ésotérique).
Ce moteur permet de faire la distinction entre la logique applicative et la couche de présentation.
Inconvénients▲
PHP < 5
Les messages d'erreurs pourraient être plus explicites.
Conclusion▲
J'aime beaucoup cette manière d'utiliser les templates. C'est simple à utiliser et l'idée des commentaires HTML est excellente, car il n'y a pas besoin d'apprendre une nouvelle syntaxe.
Un résumé est disponible en fin d'article.