Revenir
en haut

Utiliser un moteur de template avec PHP, pourquoi ?

23/11/2010 5

Pendant longtemps j’ai dénigré les moteurs de template comme Smarty & Co. Tout simplement parce qu’en pesant les pours et les contres, les contres l’emportaient toujours. Le principal argument serait : « PHP est lui même un moteur de rendu, pourquoi ajouter une couche supplémentaire pour faire exactement la même chose ? ».

Premièrement, PHP a évolué, et même si son inventeur, Rasmus Lerdorf, l’a crée dans le but de dynamiser plus facilement son code HTML, le langage a depuis beaucoup changé. Il s’est professionnalisé, son modèle objet est devenu robuste, et avec la démocratisation des bonnes pratiques de développement web et notamment la séparation « of concerns » (qui peut me donner la bonne traduction ?), il est devenu bien plus qu’un simple moteur de rendu.

Ensuite, avec le recul et après avoir expérimenté pas mal de projets MVC dans lesquels la couche présentation (vues) est construite avec PHP, la question d’utiliser un moteur de templates revient naturellement.

Ce thème est sujet à débats, et vous ne serez certainement pas tous d’accord avec mes arguments, tout comme moi auparavant. Je vais tenter de vous faire comprendre pourquoi je suis revenu sur mes positions.

La preuve par l’exemple

Pour vous aider à comprendre ce qui me fait changer d’avis, jetons un coup d’oeil au script de vue suivant :

<?php
// <title></title>
$this->headTitle($this->escape($this->video->title));

$this->headMeta()->appendName('description', $this->excerpt($this->escape($this->video->description), 200, true));

$this->headScript()->appendFile('videos.js');
$this->placeholder('title1')->set($this->escape($this->video->title));
?>

<?php /* Video owner action */ ?>
<?php if ($this->auth->isAllowed($this->currentUser, $this->video, 'edit')) : ?>
    <div class="actions">
        <ul>
            <li>
                <a href="<?php echo $this->url(array('controller' => 'videos', 'action' => 'edit', 'id' => $this->video->id), 'default'); ?>">
                    Editer
                </a>
            </li>
            <li>
                <a href="<?php echo $this->url(array('controller' => 'videos', 'action' => 'delete', 'id' => $this->video->id), 'default'); ?>">
                    Supprimer
                </a>
            </li>
        </ul>
    </div>
<?php endif; ?>

<?php /* Video <object> */ ?>
<div class="video">
    <div class="video-inner">
        <?php echo $this->getVideoObject($this->video->code); ?>
    </div>          
</div>

<?php /* Video details */ ?>
<div class="video-details">
    <div class="description">
        <?php echo nl2br($this->escape($this->video->description)); ?>
    </div>
    <div class="author">
        <a href="<?php echo $this->url(array('id' => $this->video->user->id), 'user_route'); ?>"
           title="Voir le profil de <?php echo $this->escape($this->video->user->login); ?>">
           <?php echo $this->escape($this->video->user->login); ?>
        </a>
    </div>
</div>

<?php /* List of video comments */ ?>
<div class="comments">
    <?php foreach($this->comments as $comment) : ?>
        <div class="comment-item" id="comment-<?php echo $comment->id; ?>">
            <div class="comment-author">
                <a href="<?php echo $this->url(array('id' => $comment->user->id), 'user_route'); ?>"
                   title="Voir le profil de <?php echo $this->escape($comment->user->login); ?>">
                   <?php echo $this->escape($comment->user->login); ?>
                </a>
            </div>
            <div class="comment-text">
                <?php echo nl2br($this->escape($comment->text)); ?>
            </div>
            <div class="comment-actions">
                <ul>
                    <?php if ($this->auth->isAllowed($this->currentUser, $this->video, 'comment')) : ?>
                        <li>
                            <a href="<?php echo $this->url(array('controller' => 'videos', 'action' => 'add-comment', 'id' => $this->video->id), 'default', true); ?>">
                                Ajouter
                            </a>
                        </li>
                    <?php endif; ?>
                       
                    <?php if ($this->auth->isAllowed($this->currentUser, $comment, 'edit')) : ?>
                        <li>
                            <a href="<?php echo $this->url(array('controller' => 'videos', 'action' => 'edit-comment', 'id' => $comment->id), 'default', true); ?>">
                                Editer
                            </a>
                        </li>                                                    
                    <?php endif; ?>
                </ul>
            </div>
        </div>
    <?php endforeach; ?>
</div>

Vous l’aurez compris, il s’agit d’une vue qui affiche une vidéo d’un utilisateur, avec ses commentaires. L’exemple est simplifié, pas de traductions, pas d’avatars pour les auteurs, pas de partials, etc. Et ici je ne parle même pas du layout.

Osez me dire que c’est facile à maintenir ! :p

Des $this et des < ?php echo … ?>, mangez-en…

Sur un de nos projets, nous nous sommes finalement perdus et c’est devenu très difficile de maintenir la couche présentation du site.

De plus, lors de l’intégration, nous sommes souvent tentés de faire du traitement dans les vues, chose à éviter, la vue affiche les données et c’est tout, il ne faut pas mélanger les responsabilités de chaque couche de l’application. Un moteur de templates aide à résoudre ce problème.

Les avantages d’un moteur de templates

Les avantages apportés par un moteur de templates tel que Twig sont simples :

Une syntaxe propre et condensée dédiée au design (réutisabilité)

Les intégrateurs peuvent se concentrer sur un langage et une syntaxe qui à priori ne changeront pas, contrairement à PHP qui évolue (dépréciation de fonctions par exemple).

Que dire de plus sur ce point, c’est aussi une histoire de goût.

Un code HTML beaucoup plus lisible

Ceci est indéniable, le code HTML devient beaucoup plus lisible, si le moteur de templates est maitrisé il y aura moins de chance de se perdre dans le code.

Ce point est facile à défendre mathématiquement. Pour afficher une variable de manière sécurisée avec PHP et Zend Framework, il faut compter au moins 36 caractères, sans compter le nom de la variable en elle-même et en supposant que nous n’accédons pas une propriété d’un objet ou une valeur de tableau.

<?php echo $this->escape($this->foo); ?>

Avec un moteur tel que Twig :

{{ foo }}

Quelque chose à ajouter ?

Interdir du traitement dans les vues

Ce point est crucial et reste pour moi un des avantages les plus importants. Impossible (en théorie) de s’enfoncer dans un code alambiqué dans lequel nous finirons par nous perdre.

Sécurité

Certains me diront que c’est au développeur de faire attention et que celui qui oublie d’échapper une variable avant de l’afficher mériterait une sanction pire que la mort. Je suis plus ou moins d’accord (mais je suis ok sur la sanction :) ).

C’est très facile dans la jungle PHP d’une vue d’oublier un « escape » ou pire, sans framework, le très verbeux « htmlspecialchars(….) ». Ça arrive au meilleur d’entre nous.

Dans la plupart des moteurs de templates il est possible d’activer un échappement automatique des variables et une intervention n’est nécessaire que si nous ne souhaitons pas échapper une expression, ce qui est quand même relativement rare. Fonctionner dans ce sens est donc logique, et nous n’avons plus besoin de nous soucier de ça. Sans parler de la lisibilité qui est largement accrue.

Je sais que dans le cas de Javascript il faut faire très attention à l’échappement des tags, mais quand bien même, c’est toujours mieux que de devoir systématiquement tout échapper à la main.

Dans un monde parfait, j’ajouterai à cette liste l’interopérabilité entre langages/framework, mais ça insinuerait une syntaxe universelle et un portage du moteur vers les différents langages, c’est toujours bon de rêver :)

Les inconvénients d’un moteur de templates

Bien entendu, rien ne vient sans son lot de problèmes :)

Voici les inconvénients majeurs d’un moteur de templates :

Coloration syntaxique dans les IDE

A moins que le moteur de templates soit suffisamment réputé pour bénéficier d’un plugin pour votre IDE, il ne faudra pas espérer avoir une coloration syntaxique (à moins de le faire soi-même), ce qui peut être frustrant.

Chute de performances. Pour certains moteurs c’est même épouvantable.

Les performances de l’application sont inévitablement touchées. Il faut parser et compiler le template en PHP, ce qui demande un certain temps. Parfois, certains moteurs pourtant assez pauvres en fonctionnalités sont une véritable catastrophe en terme de performances. Il faut donc faire très attention à ça au moment de choisir son moteur de templates.

Pour pallier à ce problème, des moteurs comme Twig ou Smarty permettent de mettre en cache le résultat de la compilation PHP des templates. Mais pour Smarty par exemple, ce n’est pas suffisant, le moteur étant devenu une véritable usine à gaz, les performances sont assez médiocres.

Un manque de fonctionnalités frustrant et dangereux

Parfois, les moteurs ne proposent pas de solutions pour obtenir ce qu’on veut, ce qui poussent à utiliser PHP quand même par des feintes pas très jolies jolies (qui se reconnait ? :p).

Difficile de parser/débugger un template

Autre point qui peut en rebuter certains. Il devient plus difficile de débugger un template. Le moteur doit soit intégrer sont propre débuggueur, soit il faut aller débugger manuellement le résultat des compilations dans le cache, je n’en dis pas plus, vous comprendrez la lourdeur de la manipulation.

Il devient également difficile de parser les fichiers. Dans le cas d’une internationalisation avec gettext par exemple. Mais ce problème n’est pas sans solution.

Casse la structure (x)HTML

Dans certains cas, les moteurs de templates cassent la structure du (x)HTML. Un exemple parfait :

<table>
    <thead>
        <tr>
            <th>Nom</th>
            <th>Prénom</th>
        </tr>
    </thead>
    <tbody>
        {% for user in users %}
            <tr>
                <td>{{ user.name }}</td>
                <td>{{ user.firstname }}</td>
            </tr>
        {% endfor %}
    </tbody>
</table>

Alors qu’en (x)HTML le W3C recommande que rien ne doit être présent entre les tags tbody et tr.

Je dirais tout simplement que c’est un faux problème étant donné qu’il existe aussi si on utilise PHP comme moteur de rendu.

Difficile d’insérer du Javascript

Conclusion

En étant pragmatique :

  • avantages : 4
  • inconvénients : 6

6 > 4, il ne faut donc pas utiliser un moteur de templates.

Non, je n’oserai pas. D’une part parce que je ne suis pas certain d’avoir cité tous les avantages et les inconvénients. D’autre part parce qu’il y a les puristes, les grand défenseurs de PHP ou de Smarty, et j’en passe.

Sachez seulement que je me suis finalement laissé séduire. Les raisons sont finalement simples, une maintenance du code beaucoup plus facile et l’arrivée de nouveaux moteurs de templates qui offrent un excellent rapport fonctionnalités/performances.

Le dernier en date qui m’a convaincu : Twig.

Je vous propose d’ailleurs une intégration de Twig avec Zend Framework 1.1x dans l’article : Utiliser Twig avec Zend Framework 1.1x

5 commentaires :

  1. Pingback: Utiliser Twig avec Zend Framework 1.1x | anonymation – blog – développement et architecture web

  2. Pingback: Amélioration de l’intégration ZF et Twig | anonymation – blog – développement et architecture web

  3. Francois :

    Bonjour, Je viens de découvrir votre blog dont l’esprit me convient particulièrement. J’ai écrit mes deux premiers sites avec Borland Delphi 5, oui, ca date ! Je me suis mis a php tardivement début 2008, pour les raisons que vous évoquez ailleurs sur votre blog, je commence à m’intéresser aux framework php ne voulant plus travailler sur windows.

    J’en viens au fait, un chose me frappe, concernant les framework Php, il s’agit de la similitude dans le modèle objet proposé avec delphi à l’époque (1999 !). Avec de grandes améliorations bien sûr. D’autre part j’ai, comme vous, du mal avec les moteurs de templates.

    Mes templates était constitués de html pur, dans lesquels j’insérait des tags de forme dédiée mais libres, le gestionnaire de vues de Delphi mes proposant un évènement pour chaque tag, je garnissait l’objet de réponse avec du code Delphi.

    Le résultat : – Un layout simple et clair, – Des vues partielles simple et modulaires encore en simple html, – Un parseur, vous vous en doutez, ultra-simple.

    J’ai travaillé récemment sur un site de e-commerce avec smarty, je me suis arraché les cheveux, comme vous en témoignez !

    Pourquoi avoir créé encore un nouveau language pour coder des templates, pour moi c’est aussi in-maintenable que l’exemple de code que vous citez.

    Au final on se retrouve avec deux choix : avoir un code ressemblant à un plat de spagettis en php, ou dans le « language » du moteur de templates !

    Je sais que je me réfère à l’histoire, mais ayant eu le gout du code en découvrant la POO en 1992, je m’aperçoit que fondamentalement les concepts sont les mêmes, mais que, pour moi, on a compliquer les choses….

    Cordialement, François M

    • Hello François,

      Merci pour votre commentaire.

      J’ai aussi commencé avec Delphi 5 ! (et PHP). Mon premier Job (il y a quelques années de ça :p) consistait essentiellement à faire communiquer des applications en Delphi avec des serveurs sous PHP.

      Concernant les moteurs de template, ce qui me retenait jusqu’à maintenant c’est l’usine à gaz que sont les Smarty & Co.

      Ce qui m’a séduit avec Twig c’est la simplicité du système et les performances.

      Avoir un langage dédié aux templates me semble logique. Ça permet de créer des fonctionnalités dédiées à l’intégration, qui parfois demandent pas mal de lignes de code en PHP.

      Quoi qu’il en soit, PHP ou autre, un langage dynamique sera toujours nécessaire dans un template. Le déguiser en un espèce de langage proche du HTML n’y change rien (par ex. avec Spring MVC en JAVA), ça reste un langage unique à apprendre.

      Un langage dédié n’est pas plus compliqué à apprendre pour un intégrateur. Au contraire, ce type de système donne plus d’armes pour accomplir des tâches courantes d’intégration.

      Pour la POO, tous les concepts que nous utilisons existent depuis des lustres oui, Martin Fowler et autres Gang of Fours sont passés par là il y a bien longtemps. Et si on regarde bien, on ne complique pas tant les choses que ça, on ne fait que tenter d’appliquer au mieux ces vieux concepts.

      Maintenant que la première génération de frameworks PHP est passées, nous assistons à une simplification des implémentations. Moins de code superflu, simple et droit au but. Je pense que commencer à utiliser un framework PHP en 2012 est vraiment plus intéressant qu’avant ;-)

  4. Le choix dépend surtout du context (gros projet, grosse équipe ?), apprendre Twig ou Smarty demande du temps, la moindre fonction perso prend plus de temps que du Php classique etc….

    Dans 90% du temps on perd plus de temps qu’on en gagne, le PHP à la base c’est simple, rapide à mettre en place … dommage que tout le monde veuille le transformer comme du Java ou .Net

    Php 5 arrive avec un nouveau tag sympa <?= qui est équivalent à <?php echo ,

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.

*

Tags HTML autorisés : <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>
Tag code : [cc lang="langage"][/cc] (ex. [cc lang="php"][/cc])