Il m'arrive parfois de travailler avec des programmeurs qui comptent moins d'expérience (et parfois) et fait surprenant, il semblerait que ça soit le cauchemar de tous et chacun lorsque vient le temps de générer une table HTML dynamique. Par dynamique, j'entends qu'elle est créée par programmation, par exemple en PHP.
Habituellement, le code est parsemé de "if", de flags pour indiquer où on est rendu et des instructions echo qui impriment une portion du code HTML ici et là. Bref, rien de facile à suivre et le résultat s'apparente rapidement à l'image qu'on se fait du code spaghetti.
De plus, ça arrive très souvent que la validation HTML ne respecte pas les standards d'évaluation de Tidy, SGML Parser ou W3C (ce que j'ai vu le plus souvent est un </td> ou </tr> qui ne ferme pas parce que le bris de séquence est mal construit).
Pour contrer cela, il existe plusieurs moyens mais je suggère une solution simple et originale : créer le tableau avant de l'afficher. Une fois que la structure du tableau (array) illustre la représentation de la table HTML, il suffira de faire une première boucle pour afficher les rangées et une deuxième imbriquée pour lister les colonnes.
Imaginons les données suivantes qui pourraient provenir d'une base de données :
$data = array(Je définis une constante qui me servira à faire les calculs nécessaires pour construire un tableau à 3 colonnes.
array('id' => 10, 'value' => 'a'),
array('id' => 20, 'value' => 'b'),
array('id' => 30, 'value' => 'c'),
array('id' => 40, 'value' => 'd'),
array('id' => 50, 'value' => 'e'),
array('id' => 60, 'value' => 'f'),
array('id' => 70, 'value' => 'g')
);
DEFINE('NB_COLS', 3);Ensuite, c'est là que la magie s'opère. L'idée est de créer une matrice où chaque indice de l'array principal représentera une rangée (TR) du tableau. À l'intérieur de chaque rangée sera créé un array qui représente les colonnes (TD) et son contenu. Pour avoir une matrice complète, il sera peut-être nécessaire d'ajouter des cellules vides au tableau.
# 7 éléments au totalPour bien comprendre ce qui se passe, je vous suggère de faire un print_r($rows) après l'appel de array_chunk(), et avant/après la boucle for. Vous aurez une meilleure idée des changements qui se sont opérés pour construire la bonne structure.
$nbElems = count($data);
# créer des regroupements de 3 éléments
$rows = array_chunk($data, NB_COLS);
# $rows contient 3 rangées
# (deux pleines et une avec un seul élément)
$nbRows = count($rows);
# 3 rangées de 3 colonnes = 9 cellules
$totalTableCells = NB_COLS * $nbRows;
# combien de cellules vides doit-on créer ?
$nbEmptyCells = $totalTableCells - $nbElems;
# ajouter les cellules vides au bon endroit
for($i=0 ; $i < NB_COLS ; $i++){
# dernière colonne
if( !isset($rows[$nbRows-1][$i]) ){
$rows[$nbRows-1][$i] = array();
}
}
Enfin, deux boucles imbriquées feront générer le tableau HTML. Remarquez à quel point le code source est clair.
<?php if( count($rows) > 0 ){ ?>Vous pouvez reprendre cet exemple dans d'autres langages, le principe demeure le même. Maintenant, je vous lance un petit défi : tentez de trouver une alternative à la boucle for qui ajoute les cellules vides dans la dernière rangée du tableau.
<table>
<?php foreach($rows as $tr){ ?>
<tr>
<?php foreach($tr as $td){ ?>
<td>
<?php if( !empty($td) ){ ?>
<?php echo $td['id']; ?>
<?php } ?>
</td>
<?php } ?>
</tr>
<?php } ?>
</table>
<?php } ?>
Le code reste quand même pas mal dégueulasse.
L'utilisation de templates est quand même plus propre.
Tu veux dire avec Smarty par exemple ? Oui, ça peut être une option intéressante mais ça implique aussi que le programmeur débutant doit apprendre le fonctionnement d'un engin de template en plus de ne pas se perdre dans sa logique PHP. Ça peut avoir l'air de rien mais pour quelqu'un de moins expérimenté ou un intégrateur, tu lui en demandes beaucoup. Pour pouvoir comprendre les avantages d'une meilleure méthode à mettre en place, le programmeur évolue généralement dans ce sens :
1. code spaghetti avec bris de séquence
2. construction d'une représentation interne qui facilite l'affichage
3. utilisation d'abstraction lorsque nécessaire (ici les templates)
Smarty toucherait seulement la troisième étape pour remplacer l'affichage du code HTML (il faudra quand même construire une structure interne appropriée si on ne veut pas oublier les TD vides à la fin de la table). De plus, il ne réduirait en rien la quantité du code et n'améliorerait pas nécessairement sa lisibilité puisqu'on y ajouterait une couche d'abstraction supplémentaire. Si vous comptez utiliser les templates, vous pouvez voir comment convertir l'affichage HTML avec Smarty (j'ai publié un exemple avec une table qui fait sensiblement la même chose). Il ne faut pas oublier que PHP est lui-même un engin de template et qu'il est bon de juger si on en a besoin ou non d'un deuxième.
Le fait est que l'un des buts du programmeur doit être de découpler du mieux possible le fond de la forme pour pouvoir traiter/modifier indépendamment l'une de l'autre si nécessaire.
Pour preuve, les taglibs et les expressions languages ont été inventés pour réduire l'insertion de code java pur dans les pages jsp (tout comme on injecte du code pur dans des pages php). Après, je présume qu'il existe des moteurs plus simples que Smarty.
Il est vrai, je l'admets, qu'il y a plus de code au final. Cependant, c'est le prix à payer pour un minimum de modularité, un peu comme utiliser un framework de développement structuré (ActionScriptFoundry, par exemple).
Certes l'apprentissage demande un investissement de départ (on peut estimer que ça fait partie du métier, après tout) mais le gain final est significatif.
Bien entendu, ce gain ne va se ressentir que sur des projets de taille certaine (comme, par exemple, pour les pratiques CMMi).
De plus, si l'écriture s'avère plus complexe au départ, elle simplifie l'évolution future du code (exemple tout bête : ajouter le support du th dans ta création de table).
Ensuite, en découplant fond et forme de cette façon, il devient plus facile de séparer les tâches. Par exemple, j'ai vu des entreprises dans lesquels les graphistes écrivaient les templates (langage plus simple, manipulation de la forme, etc.) et les programmeurs plus expérimentés écrivaient le code qui y était associé.
Enfin, PHP est une sorte de moteur de template tel que cela était pensé dans les années 90. Aujourd'hui, avec le recul, on sait qu'il est préférable, sur le long terme, de les intégrer au sein de modèles connus et éprouvés comme le Model-View-Controler ou le Presentation-Abstraction-Control (cf. les évolutions de JSP et d'ASP).
Toutefois, il est certain qu'il faut doser en fonction des projets et de leurs contraintes (temps alloué, taille, compétences et moyens disponibles, choix éventuels effectués en amont, etc.) mais sans oublier, dès que cela est possible, de penser en terme d'évolution.
Désolé pour ce long commentaire :S
Ton commentaire est long mais très pertinent. Je suis certain qu'il aidera les autres à prendre la meilleure décision.
Au fond, comme le texte s'adresse surtout aux débutants pour les aider à améliorer la logique d'un code spaghetti, j'aurais dû illustrer l'exemple avec le code avant/après.
Ton dernier paragraphe résume bien l'idée. Parfois, nous avons des projets "jetables", réalisables en quelques dizaines d'heures et qui sont d'une durée de vie limitée. Dans ce cas, on fait volontairement le choix de garder le code le plus élémentaire possible.
Lorsqu'un projet est de grande envergure, il est judicieux d'accorder plus de temps à la structure et c'est là qu'on doit se doter des meilleures pratiques et outils de programmation.