View this page in english

09 Jul 2011

Génération efficace de code HTML sans système de templating

Category: Divers ,PHP


Résumé de l'article

Le propos de cet article est de montrer que, dans le contexte d'un développement web professionnel (en PHP en l'occurrence mais ça reste valable pour d'autres langages), l'utilisation d'un générateur de HTML est meilleure qu'un système de templating. Après un tour d'horizon des solutions existantes de génération de code HTML on verra qu'il n'existe, à mon sens, rien de bien convainquant ; je proposerai alors une classe PHP, basée sur une idée originale de Jean-François Gigand, qui permet de générer vos pages HTML de façon simple, efficace, robuste, lisible et rapide en utilisant le « chaining coding style ».

Si vous êtes pressé, vous pouvez aller directement à la présentation de XmlTag.

Pourquoi les systèmes de templating PHP sont-ils néfastes ?

Pour faire court, au cas où vous n'en avez pas encore pris conscience, PHP est déjà un système de templating ; il est donc complètement inutile de rajouter un système de templating supplémentaire. Si vous n'êtes pas encore convaincu, voici quelques liens qui expliquent plus en détail pourquoi l'ajout d'un système de templating est néfaste en PHP :

Pourquoi tous les système de templating web sont à éviter ?

Je vais plus loin en affirmant que tous les systèmes de templating web (le système de templating natif de PHP inclus) donnent bien souvent un code illisible et difficilement maintenable. En voici un exemple simplifié, en général c'est souvent pire, extrait d'un thème pour WordPress. J'ai supprimé l'indentation car aucun des éditeurs que je connaisse n'indente correctement ce genre de code :

<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
<div <?php post_class(); ?> id="post-<?php the_ID(); ?>">
<?php if($show_date) :
$time = get_the_time(_c('M d Y|Dates','stardust')); ?>
<div class="date" title="<?php the_time(_c('d-m-Y|Dates','stardust')); ?>">
<p><span class="mese"><?php echo($mo); ?></span></p></div><?php endif; ?>
<h2 class="storytitle"><a href="<?php the_permalink() ?>" rel="bookmark"><?php the_title(); ?></a></h2>
<div class="meta"><span class="tags"><?php _e("Category:"); ?>
<?php the_category(',') ?></span> &#8212; <span class="user">
<?php the_author() ?> @ <?php the_time() ?></span> <?php edit_post_link(__('Edit This')); ?></div>
<div class="storycontent">
<?php if (function_exists('the_tags')): ?>
<p class="meta"><?php the_tags(__('Tags: ').' ',', '); ?></p>
<?php endif;?>
</div>
<div class="feedback">
<?php wp_link_pages(); ?>
<p><?php comments_popup_link(__('Comments (0)'), __('Comments (1)'), __('Comments (%)')); ?></p>
</div>
</div>
<?php endwhile; else: ?>
<p><?php _e('Sorry, no posts matched your criteria.'); ?></p>
<?php endif; ?>
  

Comment savoir si le code html est valide ?
Comment suivre sereinement la logique de la mise en page ?
Comment trouver facilement la fermeture d'une condition, d'une boucle ?
Comment aller à la fermeture/ouverture d'une balise ?

C'est malheureusement comme cela que les « développeurs » php apprennent à coder leurs vues et imposent aux autres, de fait, la maintenance de telles bouillies informes agrémentées parfois de Javascript généré dynamiquement qui va lui-même à son tour aller modifier le DOM… un vrai bonheur de reprendre ce genre de code, et je sais malheureusement de quoi je parle…

Les générateurs de HTML, état de l'art

Des tentatives de classes permettant de générer le code HTML directement en PHP ont déjà vu le jour à l'instar de ce qui se fait en Python avec WebHelpers (loin d'être parfait, au demeurant) ; citons :

  • phpHtmlLib. Je ne l'ai jamais utilisé mais on voit immédiatement qu'il est loin d'être intuitif à utiliser et, au regard du code source, j'émets des réserves sur ses performances. Il semble cependant être le meilleur de ma liste !
  • les helpers html de CakePHP montrent une conception très maladroite des méthodes (d'ailleurs tout CakePHP est maladroit et mal conçu, pour l'avoir utilisé pendant 10 mois j'expliquerai dans un prochain article pourquoi il ne faut pas utiliser CakePHP sur des projets sérieux). Pour en revenir à la classe HtmlHelper de ce pauvre CakePHP voici le genre de code que l'on obtient :
          echo $this->Html->tag('div',
              $this->Html->tag('span',
                  $this->Html->tag('strong', 'Hello world', null),
              array('class' => 'hello')),
          array('class' => 'welcome')
          );
          
    Autrement dit, pour modifier la classe du div de départ il faut traverser tout l'arbre html et modifier le array à la fin du code ; c'est à mourir de rire, du Cake tout craché…
  • les HTML Helper de CodeIgniter est un travail inachevé. D'autre part, faire un heading('Welcome!', 3); pour obtenir <h3>Welcome!</h3> n'a aucun intérêt voir aucun sens et le principe « une fonction par balise » ne m'inspire rien de bon d'autant plus que les fonctions n'ont pas toujours le même nom que la balise (link_tag par exemple)…
  • le projet php-html-generator est basé quant à lui sur le principe « une classe = une balise » et l'on obtient un code de ce genre :
          $div = new Div('abc');
          $div->addInner(new Span('a', new label('x', 'Labão')));
          $div->addInner(new Span('v', 'ancv'));
          $div->addInner(new Span('c', 'ancc'));
          
    Le code est beaucoup trop verbeux et manque de lisibilité !
    Le fait d'avoir des addInner ne permet pas de visualiser les imbrications par indentation, le code manque donc de lisibilité. Je n'ai pas tout testé mais ça ne me donne pas envie de regarder le reste…
  • HTML Generator : il y a une fonction pour ouvrir la balise et une pour la fermer… quand je pense que je me suis inscrit pour voir des sornettes pareilles…
  • J'arrête là le massacre…

XmlTag : une façon de générer du code HTML/XML simple, efficace, robuste et lisible

Suite à toutes les considérations précédentes, voici la classe que je propose ; elle permet de générer du HTML avec un code propre, lisible, optimisé et directement en PHP pur et dur. Ainsi le HTML suivant…

<p>
  <strong>du gras ici,</strong> <i>de l'italique ici</i>
</p>
<div class="ma_super_classe" id="leZId">
  du texte concaténé avec <span style="color:red"><i>de l'italique rouge</i></span>
</div>
<div>
  <p>
    Encore un pour la route
  </p>
</div><br />

  
…est obtenu avec le code PHP suivant :
$xmlTag
->P($xmlTag()
    ->STRONG('du gras ici, ')->I('de l\'italique ici')
)
->DIV(array(
        'class' => 'ma_super_classe',
        'id' => 'leZId',
    ), $xmlTag('du texte concaténé avec ')
    ->SPAN(array('style' => 'color:red'), $xmlTag()
        ->I('de l\'italique rouge')
    )
)
->DIV($xmlTag()
    ->P('Encore un pour la route'))
->BR();

echo $xmlTag;

  

En réalité on obtient un code HTML optimisé sur une seule ligne mais, en phase de développement, on peut appliquer un filtre Tidy qui indente le code HTML pour le rendre plus lisible, comme je l'ai fait ici.

Les avantages de xmlTag

  • inutile d'apprendre un nouveau langage de templating ;
  • xmlTag est plus rapide que n'importe quel système de templating externe ;
  • le code est lisible, même par un webdesigner allergique à la programmation ;
  • on est sûr que le HTML généré est valide ; il est impossible d'oublier une balise fermante ou de fermer les balises dans le mauvais ordre ;
  • le code PHP est toujours correctement indenté, quelque soit l'IDE que l'on utilise ;
  • on peut parcourir très rapidement la structure du code en utilisant les groupes de parenthèses (aka parentheses matching) ; fonctionnalité présente dans tous les IDE ;
  • le code HTML généré est optimisé, inutile de passer par une solution comme celles proposées à la fin de cette page.

Documentation

Pour plus d'information, on se reportera aux exemples complets d'utilisation de la classe XmlTag

Télécharger XmlTag