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

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


précédentsommairesuivant

III. phpBB2 (PHP Base Library - phplib)

III-A. Présentation

Image non disponible Image non disponible

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 sont 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.

MyTemplate.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.
<?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 :

phpbb2.php
Sélectionnez
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() :

phpbb2.php
Sélectionnez
$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 :

header.php
Sélectionnez
$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 :

header.tpl
Sélectionnez
...

<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 :

home.php
Sélectionnez
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 :

home.tpl
Sélectionnez
<!-- 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 :

home.php
Sélectionnez
$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'])
                )
            );
        }
    }
}
home.tpl
Sélectionnez
<!-- 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 :

home.php
Sélectionnez
        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());
            }
        }
home.tpl
Sélectionnez
        <!-- 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 :

home.php
Sélectionnez
        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
                )
            );
        }
home.tpl
Sélectionnez
        <!-- 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 :

 
Sélectionnez
$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 besooin d'apprendre un nouveau langage esoté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.


précédentsommairesuivant

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Copyright © 2006 Guillaume Rossolini. Aucune reproduction, même partielle, ne peut être faite de ce site et 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.