Les fonctions de bufferisation de sortie permettent de mieux contrôler ce qui est affiché par PHP. Le nom peut paraître compliqué, mais le principe est simple : au lieu d'afficher directement le contenu, on le garde temporairement en mémoire pour le récupérer plus tard. C'est particulièrement utile lorsqu'on organise une application avec un routeur, des templates et un layout commun.
Le problème avec le layout
Dans l'organisation précédente, on chargeait généralement le header avant le template, puis le footer après.
Cette approche fonctionne, mais elle a une limite : le header est inclus avant le template. Si on veut définir le titre ou la description de la page depuis le template, c'est trop tard, car le header a déjà été affiché.
On aimerait pouvoir écrire dans templates/contact.php :
Puis utiliser ces variables dans un fichier de layout.
Pour que cela fonctionne, il faut d'abord exécuter le template, récupérer son contenu dans une variable, puis seulement ensuite charger le layout.
Le rôle de la bufferisation
Quand on utilise require, PHP affiche directement le contenu généré par le fichier inclus. Les fonctions de bufferisation permettent de changer ce comportement. On va créer une mémoire tampon : tout ce qui devrait être affiché est gardé en mémoire. On peut ensuite choisir de récupérer ce contenu, de l'afficher ou de le supprimer.
À partir de l'appel à ob_start(), le contenu n'est plus envoyé directement en sortie. Il est stocké dans un tampon.
Supprimer ou afficher le tampon
Plusieurs fonctions permettent ensuite d'agir sur ce tampon.
Avec ob_flush(), on envoie le contenu du tampon vers la sortie.
Récupérer le contenu avec ob_get_clean()
La fonction la plus intéressante dans notre cas est ob_get_clean(). Elle permet de récupérer le contenu courant du tampon, puis de l'effacer.
Ici, $content contient la chaîne Salut. Le contenu n'a pas été affiché directement, il a été capturé dans une variable.
Cela fonctionne aussi avec du HTML écrit en dehors des balises PHP.
Le tampon garde tout ce qui aurait dû être affiché, qu'il s'agisse d'un echo ou de HTML classique.
Appliquer la bufferisation aux templates
Dans notre application, on peut utiliser cette logique pour capturer le rendu du template.
Le fichier contact.php peut définir des variables comme $pageTitle ou $pageDescription, puis générer le HTML de la page. Tout ce HTML sera capturé dans $pageContent.
Ensuite, le layout peut afficher les métadonnées et insérer le contenu au bon endroit.
Avec cette organisation, on n'a plus besoin de séparer header.php et footer.php. On peut utiliser un seul fichier layout.php, qui représente la structure complète de la page.
Ajouter du contenu spécifique à une page
Le même principe peut être utilisé pour définir du contenu additionnel dans une page, par exemple du JavaScript spécifique.
Dans le layout, on peut prévoir une variable facultative.
Puis, dans un template, on peut capturer un script avec un second niveau de bufferisation.
Les tampons peuvent être imbriqués. Si un ob_start() est lancé dans un template alors qu'un autre tampon est déjà actif autour du template, ob_get_clean() récupère seulement le dernier niveau ouvert. Cela permet de capturer proprement différentes parties d'une page sans les afficher immédiatement.
Séparer les routes de la logique principale
Une fois cette structure en place, le fichier public/index.php peut rester très simple. Il contient la logique générale : charger l'autoloader, initialiser le routeur, trouver la route, capturer le template et charger le layout.
Pour éviter de modifier constamment ce fichier, on peut déplacer la déclaration des routes dans un fichier dédié.
Dans public/index.php, on charge simplement la configuration.
L'intérêt est de séparer la logique principale de l'application et la déclaration des routes. On ne touche presque plus à index.php, et on ajoute ou modifie les pages depuis config/routes.php.
À retenir
La bufferisation de sortie permet de capturer ce que PHP aurait normalement affiché directement. Avec ob_start() et ob_get_clean(), on peut récupérer le rendu d'un template dans une variable, puis l'insérer dans un layout.
Cette approche permet notamment de :
- définir le titre et la description depuis le template.
- utiliser un layout unique au lieu d'un header et d'un footer séparés.
- capturer du contenu spécifique à une page, comme du JavaScript.
- mieux séparer les templates, les routes et la logique principale.