Pourquoi utiliser une classe pour générer des tableaux HTML ?
Un tableau HTML se répète souvent à l'identique sur un site : une balise <table>, des <th> pour les colonnes, des <td> pour les valeurs. Écrire ce code à la main à chaque fois marche, mais le jour où on veut changer une bordure ou ajouter une classe CSS, il faut retrouver chaque tableau du site un par un. Une classe en programmation orientée objet (POO) est un modèle qui regroupe dans un même endroit les données et les actions qui s'y rapportent. Ici, la classe tableHtml regroupe toutes les actions liées à l'affichage d'un tableau, si bien qu'un seul fichier suffit pour changer le comportement de tous les tableaux du site.
En résumé : une classe évite de recopier le même code HTML à chaque tableau et centralise les modifications dans un seul fichier. C'est tout l'intérêt de la POO appliquée à un cas aussi simple qu'un tableau.
Étape 1 — Écrire la classe tableHtml dans classTable.php
On commence par créer le fichier classTable.php, qui contiendra uniquement la classe — pas d'affichage direct, juste les outils. Chaque méthode correspond à une partie du tableau : démarrer, afficher une ligne, afficher plusieurs lignes, terminer.
<?php
class tableHtml
{
// démarre le tableau, affiche l'en-tête si un tableau de colonnes est fourni
function start($header = FALSE)
{
print("<table border=\"1\">\n");
if (is_array($header))
{
print("<tr>\n");
foreach ($header as $h)
{
print("<th>" . strtoupper($h) . "</th>\n");
}
print("</tr>\n");
}
}
// ferme la balise table
function end()
{
print("</table>\n\n");
}
// affiche une ligne, avec un intitulé optionnel dans la colonne de gauche
function printRow($label, $field)
{
print("<tr>\n");
if ($label !== "")
{
print("<th>" . strtoupper($label) . "</th>\n");
}
if (!is_array($field))
{
$field = array($field);
}
foreach ($field as $value)
{
print("<td>");
print($value === "" ? " " : $value);
print("</td>\n");
}
print("</tr>\n");
}
// affiche plusieurs lignes d'un coup, en confiant chaque ligne à printRow()
function printSet($set)
{
foreach ($set as $field)
{
if (isset($field['label']))
{
$label = $field['label'];
unset($field['label']);
}
else
{
$label = "";
}
// $this, pas le nom de la classe : voir l'erreur fréquente plus bas
$this->printRow($label, $field);
}
}
}
?>
La méthode printSet() accepte un tableau de lignes. Si une ligne contient une clé 'label', cette valeur devient l'intitulé de gauche et le reste s'affiche normalement ; sinon, l'intitulé est vide et toutes les valeurs vont dans des <td>. C'est ce deuxième cas qu'on utilise à l'étape 4.
Étape 2 — Vérifier que la classe fonctionne : un tableau vide
Avant d'ajouter du contenu, on vérifie que la classe s'instancie correctement. Instancier une classe, c'est créer un objet concret à partir du modèle avec le mot-clé new — c'est cet objet, et non le nom de la classe, qu'on utilise ensuite pour appeler les méthodes.
<?php
require_once("classTable.php");
$table = new tableHtml();
$table->start();
$table->end();
?>
Résultat attendu :
<table border="1"> </table>
Un tableau vide, sans ligne ni en-tête : c'est normal, on n'a rien demandé de plus pour l'instant. Ce résultat confirme surtout que le fichier se charge et que l'objet est bien créé.
⚠ Si vous obtenez Fatal error: Uncaught Error: Non-static method tableHtml::start() cannot be called statically, c'est que le code appelle la méthode à l'ancienne, directement sur le nom de la classe (tableHtml::start()), sans objet. Depuis PHP 8, cette syntaxe n'est plus tolérée : il faut instancier avec new puis appeler la méthode sur l'objet, comme dans l'exemple ci-dessus.
Étape 3 — Ajouter un en-tête de colonnes : à quoi sert start($header) ?
La méthode start() accepte un tableau optionnel de titres de colonnes. Quand ce paramètre est fourni, la méthode ajoute une ligne <tr> avec un <th> par titre, passé en majuscules grâce à strtoupper() pour garder un rendu homogène quelle que soit la casse saisie au départ.
<?php
require_once("classTable.php");
$table = new tableHtml();
$table->start(array('Objets', 'cours - Programmation orientee objet'));
$table->end();
?>
Résultat attendu :
<table border="1"> <tr> <th>OBJETS</th> <th>COURS - PROGRAMMATION ORIENTEE OBJET</th> </tr> </table>
Les deux titres passés en paramètre deviennent les deux colonnes du tableau, tous les deux en majuscules. Rien n'apparaît encore dans le corps du tableau : c'est le rôle des méthodes suivantes.
Étape 4 — Afficher une ligne avec un intitulé à gauche : printRow()
Certains tableaux présentent leurs intitulés verticalement, sur la colonne de gauche, plutôt qu'en en-tête horizontal — un tableau de spécifications techniques, par exemple. C'est exactement ce que fait printRow($label, $field) : le premier argument devient l'intitulé de la ligne, le second (une valeur seule ou un tableau de valeurs) remplit les cellules qui suivent.
<?php
require_once("classTable.php");
$table = new tableHtml();
$table->start();
$table->printRow('ligne 1', 'Début du tableau');
$table->printRow('ligne 2', 'Introduire les lignes du tableau');
$table->printRow('ligne 3', 'Fin du tableau');
$table->end();
?>
Résultat attendu :
<table border="1"> <tr> <th>LIGNE 1</th> <td>Début du tableau</td> </tr> <tr> <th>LIGNE 2</th> <td>Introduire les lignes du tableau</td> </tr> <tr> <th>LIGNE 3</th> <td>Fin du tableau</td> </tr> </table>
Trois lignes, chacune avec son intitulé à gauche en majuscules et sa valeur à droite. On aurait pu passer un tableau de plusieurs valeurs en second argument — printRow() les aurait toutes affichées dans des <td> successifs sur la même ligne.
Étape 5 — Afficher plusieurs lignes d'un coup avec printSet()
Appeler printRow() ligne par ligne devient vite fastidieux dès qu'on a une dizaine d'entrées à afficher. printSet() résout ce problème : elle prend un tableau de lignes et délègue chacune à printRow(). Quand aucune clé 'label' n'est présente dans une ligne, l'intitulé de gauche reste vide et toutes les valeurs se retrouvent en cellules <td> classiques — ce qui convient bien à un en-tête de colonnes déjà défini par start().
<?php
require_once("classTable.php");
$table = new tableHtml();
$table->start(array('Objets', 'cours - Programmation orientee objet'));
$table->printSet(array(
array("L'approche objet", 'les classes PHP'),
array('Les classes en PHP', 'POO en PHP'),
array('Exemples', 'Générer les tableaux HTML en PHP')
));
$table->end();
?>
Résultat attendu :
<table border="1"> <tr> <th>OBJETS</th> <th>COURS - PROGRAMMATION ORIENTEE OBJET</th> </tr> <tr> <td>L'approche objet</td> <td>les classes PHP</td> </tr> <tr> <td>Les classes en PHP</td> <td>POO en PHP</td> </tr> <tr> <td>Exemples</td> <td>Générer les tableaux HTML en PHP</td> </tr> </table>
Trois lignes générées en un seul appel, sous l'en-tête posé par start(). Si l'une des lignes avait contenu une clé 'label', par exemple array('label' => 'Note', 'Voir remarque'), cette ligne-là aurait affiché un intitulé à gauche comme à l'étape 4 — les deux comportements cohabitent dans le même tableau, ligne par ligne.
En résumé : printSet() ne réinvente rien, elle appelle simplement printRow() pour chaque ligne du tableau qu'on lui passe — d'où l'appel $this->printRow(...) et non tableHtml::printRow(...) à l'intérieur de la classe.
Étape 6 — Séparer la classe et la page d'affichage : afficherTableau.php
Dans un projet réel, on garde la classe dans son propre fichier — classTable.php — et on l'utilise depuis une page distincte, ici afficherTableau.php, qui rassemble les deux démonstrations précédentes dans une vraie page HTML.
<?php
require_once("classTable.php");
?>
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Formatage des tableaux HTML avec PHP</title>
</head>
<body>
<p>Tableau avec les intitulés à gauche :</p>
<?php
$table = new tableHtml();
$table->start();
$table->printRow('ligne 1', 'Début du tableau');
$table->printRow('ligne 2', 'Introduire les lignes du tableau');
$table->printRow('ligne 3', 'Fin du tableau');
$table->end();
?>
<p>Tableau avec l'en-tête en haut :</p>
<?php
$table2 = new tableHtml();
$table2->start(array('Objets', 'cours - Programmation orientee objet'));
$table2->printSet(array(
array("L'approche objet", 'les classes PHP'),
array('Les classes en PHP', 'POO en PHP'),
array('Exemples', 'Générer les tableaux HTML en PHP')
));
$table2->end();
?>
</body>
</html>
Résultat attendu : la page affiche successivement les deux tableaux détaillés aux étapes 4 et 5 — le premier avec ses intitulés à gauche, le second avec son en-tête de colonnes en haut — chacun bordé, comme défini par border="1" dans start().
⚠ Si le navigateur affiche Fatal error: Uncaught Error: Class "tableHtml" not found, c'est que require_once("classTable.php") manque ou pointe vers un chemin incorrect : les deux fichiers doivent se trouver dans le même dossier.
Récapitulatif : le cycle complet en un seul script
Pour tester rapidement sans créer deux fichiers séparés, voici la classe et son utilisation réunies dans un seul script, prêt à copier-coller :
<?php
class tableHtml
{
function start($header = FALSE)
{
print("<table border=\"1\">\n");
if (is_array($header))
{
print("<tr>\n");
foreach ($header as $h)
{
print("<th>" . strtoupper($h) . "</th>\n");
}
print("</tr>\n");
}
}
function end()
{
print("</table>\n\n");
}
function printRow($label, $field)
{
print("<tr>\n");
if ($label !== "")
{
print("<th>" . strtoupper($label) . "</th>\n");
}
if (!is_array($field))
{
$field = array($field);
}
foreach ($field as $value)
{
print("<td>");
print($value === "" ? " " : $value);
print("</td>\n");
}
print("</tr>\n");
}
function printSet($set)
{
foreach ($set as $field)
{
if (isset($field['label']))
{
$label = $field['label'];
unset($field['label']);
}
else
{
$label = "";
}
$this->printRow($label, $field);
}
}
}
$table = new tableHtml();
$table->start();
$table->printRow('ligne 1', 'Début du tableau');
$table->printRow('ligne 2', 'Introduire les lignes du tableau');
$table->printRow('ligne 3', 'Fin du tableau');
$table->end();
$table2 = new tableHtml();
$table2->start(array('Objets', 'cours - Programmation orientee objet'));
$table2->printSet(array(
array("L'approche objet", 'les classes PHP'),
array('Les classes en PHP', 'POO en PHP'),
array('Exemples', 'Générer les tableaux HTML en PHP')
));
$table2->end();
?>
Exécuté tel quel, ce script affiche les deux tableaux vus aux étapes 4 et 5, l'un après l'autre. Pour un vrai projet, mieux vaut tout de même séparer la classe dans son propre fichier — c'est justement l'intérêt d'une classe que de pouvoir la réutiliser ailleurs sans la recopier.
Pour aller plus loin : moderniser la classe avec le typage strict
La classe fonctionne très bien telle quelle, mais elle ne dit jamais explicitement ce qu'elle attend comme paramètres. Rien n'empêche aujourd'hui d'écrire $table->printRow(42, 'test') — PHP convertira silencieusement le 42 en chaîne, et l'erreur passera inaperçue jusqu'à un rendu bizarre dans le navigateur. Le typage strict, disponible depuis PHP 7.0 et renforcé par declare(strict_types=1), évite justement cette conversion silencieuse : PHP refuse d'exécuter l'appel et signale l'erreur au bon endroit, tout de suite.
<?php
declare(strict_types=1);
class tableHtml
{
public function start(array|false $header = false): void
{
print("<table border=\"1\">\n");
if (is_array($header))
{
print("<tr>\n");
foreach ($header as $h)
{
print("<th>" . strtoupper($h) . "</th>\n");
}
print("</tr>\n");
}
}
public function end(): void
{
print("</table>\n\n");
}
// $field accepte soit une valeur unique, soit un tableau de valeurs
public function printRow(string $label, array|string $field): void
{
print("<tr>\n");
if ($label !== "")
{
print("<th>" . strtoupper($label) . "</th>\n");
}
if (!is_array($field))
{
$field = array($field);
}
foreach ($field as $value)
{
print("<td>");
print($value === "" ? " " : $value);
print("</td>\n");
}
print("</tr>\n");
}
public function printSet(array $set): void
{
foreach ($set as $field)
{
if (isset($field['label']))
{
$label = $field['label'];
unset($field['label']);
}
else
{
$label = "";
}
$this->printRow($label, $field);
}
}
}
// les arguments nommés rendent l'appel plus lisible, sans changer le résultat
$table = new tableHtml();
$table->start();
$table->printRow(label: 'ligne 1', field: 'Début du tableau');
$table->end();
?>
Résultat attendu : pour un appel correct comme celui du script ci-dessus, la sortie est identique à celle de l'étape 4 — le typage ne change rien tant que les valeurs passées sont du bon type. La différence se voit sur une erreur :
<?php declare(strict_types=1); $table = new tableHtml(); $table->printRow(1, 'test');
Résultat attendu :
Fatal error: Uncaught TypeError: tableHtml::printRow(): Argument #1 ($label) must be of type string, int given
Sans declare(strict_types=1) ni type déclaré, ce même appel aurait juste transformé silencieusement le 1 en "1" — l'erreur aurait pu se cacher pendant longtemps. Avec le typage, PHP la signale immédiatement, à l'endroit exact de l'appel fautif.
En résumé : le typage strict ne change pas le comportement d'un code déjà correct, il rend seulement les erreurs visibles plus tôt — un vrai gain quand une classe est utilisée par plusieurs personnes ou dans plusieurs pages du site.
Par carabde : 20 août 2014 | Mis à jour le 29 juillet 2026