Intégrer du PHP dans le HTML

Introduction

Dans le chapitre précédent, nous avons construit un modèle de page dynamique avec un en-tête et un pied de page réutilisables. Cependant, le contenu de ce modèle reste statique, le titre dans la balise <title>, les liens du menu, la feuille de style... tout est identique sur chaque page. Pour rendre chaque page unique, nous devons apprendre à injecter des valeurs PHP dans notre code HTML.

C'est aussi l'occasion d'aborder des outils et bonnes pratiques essentiels pour écrire du PHP mêlé au HTML de manière propre, lisible et sécurisée.

Afficher des valeurs PHP dans le HTML

La balise <?= ?>

Vous connaissez déjà echo pour afficher du texte. Dans un fichier qui mélange HTML et PHP, on l'utilise entre les balises d'ouverture et de fermeture PHP


                    <title><?php echo $pageTitre; ?></title>
                

Comme cette opération est très fréquente, PHP propose un raccourci, la balise <?= ?>, strictement équivalente à <?php echo ?>


                    <title><?= $pageTitre ?></title>
                

Les deux écritures produisent exactement le même résultat. Le raccourci <?= ?> est aujourd'hui considéré comme une bonne pratique pour l'affichage de valeurs dans le HTML, car il rend le code plus concis et plus lisible.

L'opérateur de fusion null ??

Que se passe-t-il si vous oubliez de définir la variable $pageTitre avant d'inclure header.php ? PHP génère un avertissement (Warning: Undefined variable) et la balise <title> risque de rester vide. Pour éviter ce problème, on peut utiliser l'opérateur de fusion null ??.


                    <title><?= $pageTitre ?? 'Mon Site Web' ?></title>
                

L'opérateur ?? vérifie si la valeur à sa gauche existe et si elle est différente de null. Si c'est le cas, elle est utilisée. Dans le cas contraire, c'est la valeur à sa droite qui sert de remplacement. Ici, si $pageTitre n'est pas défini ou vaut null, le titre affichera Mon Site Web.

Cette valeur par défaut sert surtout de sécurité pour éviter un titre vide. En pratique, il vaut mieux définir un titre précis pour chaque page, car la balise <title> aide à décrire correctement son contenu, aussi bien pour l'utilisateur que pour le référencement.

L'opérateur ternaire

L'opérateur ternaire permet d'écrire une condition compacte qui produit une valeur. Sa syntaxe est condition ? valeurSiVrai : valeurSiFaux


                    <p class="<?= $estEnStock ? 'disponible' : 'rupture' ?>">
                        <?= $estEnStock ? 'En stock' : 'Rupture de stock' ?>
                    </p>
                

L'opérateur ternaire permet de faire un choix simple entre deux valeurs sans écrire un if/else complet dans le HTML. Cela rend le code plus léger dans les cas courts. En revanche, dès que la logique se complique ou que les valeurs deviennent longues, lu'itlisation des blocs if/else est préférable pour garder un code lisible.

Échapper les valeurs affichées avec htmlspecialchars()

Lorsqu'on affiche une variable dans du HTML, il faut se demander d'où provient le contenu de cette variable ? Si elle provient d'une source que vous ne contrôlez pas entièrement (une saisie utilisateur, une base de données, un paramètre d'URL...), elle pourrait contenir des caractères spéciaux HTML, voire du code malveillant.

Prenons un exemple. Imaginons un site avec une zone de commentaires. Chaque commentaire est stocké en base de données puis affiché sur la page pour tous les visiteurs


                    <div class="commentaire">
                        <p><?= $commentaire ?></p>
                    </div>
                

Si un utilisateur écrit Super article, merci !, tout va bien. Mais si un utilisateur malveillant écrit <script>alert('Piraté !')</script>, ce code sera injecté tel quel dans le HTML de la page et exécuté par le navigateur de chaque visiteur qui consulte les commentaires. C'est ce qu'on appelle une faille XSS (Cross-Site Scripting). Dans la réalité, un attaquant n'afficherait pas une simple alerte, il pourrait tenter de voler des cookies de session, rediriger les visiteurs vers un site frauduleux, ou modifier l'apparence de la page.

La fonction htmlspecialchars() protège contre ce risque en convertissant les caractères spéciaux HTML en entités HTML. Une entité HTML est une séquence de caractères que le navigateur reconnaît et qu'il traduit visuellement par le caractère correspondant, sans l'interpréter comme du code. Par exemple, < est converti en &lt;, et > en &gt;


                    <div class="commentaire">
                        <p><?= htmlspecialchars($commentaire, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') ?></p>
                    </div>
                

Concrètement, si le commentaire malveillant contenait <script>alert('Piraté !')</script>, voici ce que le navigateur reçoit dans le code source de la page


                    <div class="commentaire">
                        <p>&lt;script&gt;alert(&#039;Piraté !&#039;)&lt;/script&gt;</p>
                    </div>
                

Ce code source peut paraître étrange à première vue, mais c'est exactement le comportement souhaité. Le navigateur ne voit plus de balise <script>, il ne voit que des entités HTML qu'il traduit en caractères affichables. Le résultat visible à l'écran pour le visiteur sera simplement le texte <script>alert('Piraté !')</script> affiché tel quel, comme du texte brut, sans aucune exécution de code. L'apparence de la page est normale, seul le code source contient les entités.

Les paramètres de htmlspecialchars()

La signature complète de la fonction est htmlspecialchars($valeur, $flags, $encodage). Le deuxième paramètre contrôle quels caractères sont convertis et comment les erreurs d'encodage sont gérées. Le troisième précise l'encodage du texte.

Les options les plus utiles à connaître sont les suivantes

  • ENT_QUOTES convertit les guillemets simples (') en plus des guillemets doubles ("). C'est particulièrement utile lorsqu'une valeur est affichée dans un attribut HTML.
  • ENT_SUBSTITUTE remplace les séquences d'octets invalides par le caractère de remplacement Unicode au lieu de produire un résultat incomplet ou imprévisible.
  • 'UTF-8' indique explicitement l'encodage attendu, ce qui rend le code plus clair et évite de dépendre uniquement de la configuration du serveur.

Depuis PHP 8.1, les options par défaut de htmlspecialchars() incluent déjà ENT_QUOTES et ENT_SUBSTITUTE. Dans un projet moderne bien configuré, un appel comme htmlspecialchars($valeur) donne donc souvent un résultat correct.

Malgré cela, il reste conseillé d'écrire explicitement la forme complète suivante


                    htmlspecialchars($valeur, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8')
                

Cette écriture présente plusieurs avantages. Elle montre immédiatement l'intention du développeur, elle rend le code plus lisible pour quelqu'un qui ne connaît pas les valeurs par défaut, et elle évite de dépendre implicitement d'une configuration serveur qui pourrait varier.

Toute valeur dont vous ne maîtrisez pas le contenu avec certitude doit être échappée avec htmlspecialchars() avant d'être affichée dans le HTML. Pour les constantes et les valeurs que vous définissez vous-même dans le code (comme BASE_URL ou $pageTitre), ce n'est pas nécessaire car vous en contrôlez le contenu.

Application au modèle de page

Grâce à ces outils, nous pouvons maintenant rendre notre en-tête dynamique. Le principe est simple. Chaque page prépare d'abord les valeurs dont elle a besoin, puis inclut le fichier qui les affiche.

Fichier index.php


                    <?php
                    require_once __DIR__ . '/config/config.php';

                    $pageTitre = "Accueil";
                    $metaDescription = "Page d'accueil de notre site web.";

                    // Ces variables sont définies avant l'inclusion de header.php.
                    // Le fichier header.php pourra donc utiliser $pageTitre et $metaDescription.
                    // La constante BASE_URL est elle aussi disponible, car elle a été définie
                    // dans le fichier config.php chargé juste au-dessus.
                    ?>
                    <?php require __DIR__ . '/templates/header.php'; ?>
                    <h2>Bienvenue sur notre site !</h2>
                    <p>Ceci est le contenu de la page d'accueil.</p>
                    <?php require __DIR__ . '/templates/footer.php'; ?>
                

Fichier header.php (version dynamique)


                    <!DOCTYPE html>
                    <html lang="fr">
                    <head>
                        <meta charset="UTF-8">
                        <meta name="viewport" content="width=device-width, initial-scale=1.0">
                        <meta name="description" content="<?= $metaDescription ?? '' ?>">
                        <title><?= $pageTitre ?? 'Mon Site Web' ?></title>
                        <link rel="stylesheet" href="<?= BASE_URL ?>/assets/css/style.css">
                    </head>
                    <body>
                        <header>
                            <nav>
                                <ul>
                                    <li><a href="<?= BASE_URL ?>/">Accueil</a></li>
                                    <li><a href="<?= BASE_URL ?>/contact.php">Contact</a></li>
                                </ul>
                            </nav>
                        </header>
                        <main>
                

Ce mécanisme repose sur la portée des variables en PHP. Lorsqu'un fichier est inclus avec require, il peut utiliser les variables définies dans le fichier appelant, à condition que celles-ci se trouvent dans la même portée, donc en dehors de toute fonction ou classe.

Dans ce petit projet, importer config.php en haut de chaque page reste une solution simple et pratique. Comme ce fichier contient une constante utile sur toutes les pages, cette approche évite de compliquer inutilement la structure du projet.

Dans un projet plus structuré, on cherche cependant à éviter de répéter les mêmes inclusions dans chaque page. Plus tard, lorsque nous verrons une organisation de type MVC, toutes les requêtes passeront d'abord par un fichier unique. Ce fichier central se chargera d'importer la configuration et les éléments communs avant d'appeler la bonne page. Dans ce contexte, il n'est donc plus nécessaire d'importer le fichier de configuration dans chaque page séparément.

Structures de contrôle dans le HTML

Il arrive fréquemment qu'on doive afficher du HTML de manière conditionnelle ou répéter un bloc HTML pour chaque élément d'un tableau. Vous connaissez déjà les structures de contrôle avec la syntaxe à accolades. Voyons comment les utiliser dans un contexte HTML, puis découvrons une syntaxe alternative plus adaptée.

La syntaxe avec accolades

On peut utiliser la syntaxe classique en ouvrant et fermant les balises PHP autour de chaque partie de la structure de contrôle


                    <?php if ($estConnecte) { ?>
                        <p>Bienvenue, <?= $nomUtilisateur ?> !</p>
                    <?php } else { ?>
                        <p>Veuillez vous connecter.</p>
                    <?php } ?>
                

De même pour une boucle


                    <ul>
                    <?php foreach ($articles as $article) { ?>
                        <li><?= $article ?></li>
                    <?php } ?>
                    </ul>
                

Cette syntaxe fonctionne, mais lorsque le HTML s'étend sur de nombreuses lignes ou que les structures sont imbriquées, les accolades fermantes deviennent difficiles à associer à leur accolade ouvrante correspondante.

La syntaxe alternative

PHP propose une syntaxe alternative conçue spécifiquement pour les fichiers mêlant PHP et HTML. Elle remplace l'accolade ouvrante par le symbole : et l'accolade fermante par un mot-clé explicite (endif, endforeach, endfor, endwhile, endswitch)


                    <?php if ($estConnecte): ?>
                        <p>Bienvenue, <?= $nomUtilisateur ?> !</p>
                    <?php else: ?>
                        <p>Veuillez vous connecter.</p>
                    <?php endif; ?>
                

                    <ul>
                    <?php foreach ($articles as $article): ?>
                        <li><?= $article ?></li>
                    <?php endforeach; ?>
                    </ul>
                

Le mot-clé de fermeture rend immédiatement visible à quelle structure il correspond, même quand le bloc HTML entre les deux est long ou quand plusieurs structures sont imbriquées les unes dans les autres.

Quelle syntaxe utiliser ?

Voici la convention généralement adoptée :

  • Dans un fichier de logique pure (un fichier PHP qui ne contient pas de HTML), utilisez la syntaxe classique avec accolades. C'est ce que vous faites depuis le début du cours et ça reste la norme dans ce contexte.
  • Dans un fichier qui mélange PHP et HTML (comme un template), privilégiez la syntaxe alternative. Elle est plus lisible dans ce contexte et c'est la convention largement adoptée par la communauté PHP.

Organiser son code

Lorsqu'un fichier PHP doit effectuer un traitement (préparer des données, vérifier une condition, appeler une fonction...) et afficher du HTML, il faut toujours placer la logique PHP en haut du fichier, et l'affichage HTML en dessous.


                    <?php
                    // === LOGIQUE ===
                    // Définition des variables, appels de fonctions, traitements...
                    $pageTitre = "Articles";
                    $articles = ["Premier article", "Deuxième article", "Troisième article"];
                    ?>

                    <!-- === AFFICHAGE === -->
                    <?php require __DIR__ . '/templates/header.php'; ?>

                    <h2><?= $pageTitre ?></h2>
                    <ul>
                    <?php foreach ($articles as $article): ?>
                        <li><?= $article ?></li>
                    <?php endforeach; ?>
                    </ul>

                    <?php require __DIR__ . '/templates/footer.php'; ?>
                

Cette organisation présente plusieurs avantages. Elle rend le code plus facile à lire, car on distingue rapidement ce qui appartient au traitement et ce qui appartient à l'affichage. Elle réduit aussi la quantité de PHP présente dans le HTML en la limitant aux affichages simples et aux structures de contrôle de base. Enfin, elle vous évitera certains problèmes techniques que nous aborderons dans un prochain chapitre.

En règle générale, si une logique est complexe (plusieurs conditions imbriquées, manipulations de données, calculs, etc.), encapsulez-la dans une fonction que vous définirez ou appellerez dans la partie logique du fichier, puis contentez-vous d'afficher le résultat dans la partie HTML. Le HTML devrait idéalement ne contenir que des affichages simples et des boucles ou conditions portant sur des données déjà préparées.

Stocker du Code HTML dans une Variable PHP

Il est parfois utile de capturer un bloc de code HTML dans une variable PHP plutôt que de l'afficher immédiatement. Cela permet par exemple de construire un fragment HTML dans une fonction, puis de l'injecter à un endroit précis de la page.

Il existe plusieurs façons de procéder en PHP :

  • la concaténation de chaînes,
  • la syntaxe Heredoc,
  • ou encore la mise en mémoire tampon avec ob_start().

Dans ce cours, nous utiliserons cette dernière technique car elle offre un avantage décisif par rapport aux autres, elle vous permet d'écrire du HTML exactement comme vous le feriez normalement, avec l'indentation naturelle, les retours à la ligne et la coloration syntaxique de votre éditeur de code. De plus, vous pouvez y intégrer toute la syntaxe PHP (variables, boucles, conditions), ce que la concaténation ou le Heredoc rendent beaucoup moins lisible, voire impossible.

La mise en mémoire tampon : ob_start()

La fonction ob_start() (output buffering start) demande à PHP de retenir en mémoire tout ce qui serait normalement envoyé au navigateur. La fonction ob_get_clean() récupère le contenu actuellement stocké dans la mémoire tampon, le supprime du tampon, puis arrête la mise en tampon.


                    <?php
                    ob_start();
                    ?>
                    <div>
                        <h2>Titre de la section</h2>
                        <p>Contenu du paragraphe.</p>
                    </div>
                    <?php
                    $html = ob_get_clean();

                    // La variable $html contient maintenant tout le HTML ci-dessus.
                    // On peut l'afficher plus tard, la modifier, etc.
                    echo $html;
                    ?>
                

Dans ce premier exemple, il n'est pas nécessaire d'utiliser htmlspecialchars(). Tout le contenu affiché est écrit directement dans le code par le développeur. Aucune valeur provenant d'une variable n'est insérée dans le HTML.

Lorsqu'il est nécessaire d'afficher plusieurs blocs semblables, il peut être utile de créer une fonction qui génère leur code HTML. Cela évite de réécrire plusieurs fois la même structure.


                    <?php
                    function genererCarte(string $titre, string $description): string
                    {
                        ob_start();
                        ?>
                        <article class="carte">
                            <h3><?= htmlspecialchars($titre) ?></h3>
                            <p><?= htmlspecialchars($description) ?></p>
                        </article>
                        <?php
                        return ob_get_clean();
                    }
                    ?>
                

Ici, les textes affichés ne sont plus écrits directement dans le code HTML. Ils sont reçus par la fonction dans les paramètres $titre et $description, puis insérés dans le HTML généré. Comme cette fonction pourrait un jour être appelée avec des valeurs provenant d'un formulaire, d'une base de données ou d'une URL, il est prudent d'échapper ces valeurs avant de les afficher dans le HTML.

Exercices

Exo-00 — Préparer la structure commune du projet

Avant de réaliser les trois exercices suivants, il faut préparer une structure de projet commune. Le but est de mettre en place un modèle de page réutilisable avec un en-tête, un pied de page, un fichier de configuration et une feuille de style.

Les exercices suivants seront réalisés dans ce même projet. Il n'est donc pas nécessaire de créer un dossier séparé pour chaque exercice.

Structure attendue


                    /exo-integrer-php-dans-le-html
                    ├── exo-01.php
                    ├── exo-02.php
                    ├── exo-03.php
                    ├── config/
                    │   └── config.php
                    ├── templates/
                    │   ├── header.php
                    │   └── footer.php
                    └── assets/
                        └── css/
                            └── style.css
                

Instructions

  1. Créer un dossier de projet nommé exo-integrer-php-dans-le-html. Placez-le dans votre environnement local, par exemple dans laragon/www sous Windows ou dans Applications/MAMP/htdocs sur Mac.
  2. Reproduire l'arborescence ci-dessus. Les fichiers exo-01.php, exo-02.php et exo-03.php peuvent rester presque vides pour l'instant.
  3. Dans le fichier config/config.php, définir une constante BASE_URL correspondant à l'URL de base du projet.
  4. Dans le fichier templates/header.php, écrire le début de la page HTML. Ce fichier doit contenir au minimum
    • la structure <!DOCTYPE html>, <html>, <head> et <body>
    • une balise <title> utilisant $pageTitre avec une valeur de secours
    • un lien vers la feuille de style avec BASE_URL
    • une navigation respectant la structure header > nav > ul > li > a
    • dans cette navigation, trois liens menant vers exo-01.php, exo-02.php et exo-03.php en utilisant BASE_URL dans les href
    • l'ouverture de la balise <main>
  5. Dans le fichier templates/footer.php, fermer les balises restantes, notamment <main>, <body> et <html>.
  6. Dans le fichier assets/css/style.css, ajouter quelques règles simples pour vérifier que la feuille de style est bien chargée. Par exemple, modifier la police, la couleur du fond ou l'apparence du menu.
  7. Vérifier dans le navigateur que
    • la feuille de style est bien chargée
    • les liens du menu utilisent correctement BASE_URL
    • la structure commune du projet est prête pour les exercices suivants

Exo-01 — Observer l'effet de htmlspecialchars()

Cet exercice a pour objectif de montrer ce qui se passe lorsqu'un texte contenant du HTML ou du JavaScript est affiché tel quel dans une page, puis après échappement avec htmlspecialchars().

Données fournies

Utiliser la donnée suivante dans la partie logique du fichier


                    <?php
                    $commentaire = "<script>alert('Test XSS')</script>";
                    ?>
                

Instructions

  1. Rendez-vous dans le fichier exo-01.php. Commencez par importer le fichier config.php en haut du fichier afin de rendre la constante BASE_URL disponible. Définissez ensuite la variable $pageTitre, puis incluez header.php avant d'écrire le contenu de la page. À la fin du fichier, incluez footer.php.
  2. Ajouter dans la partie logique la variable $commentaire fournie ci-dessus.
  3. Dans la partie HTML, afficher d'abord le commentaire tel quel, sans utiliser htmlspecialchars().
  4. Tester la page dans le navigateur. Observer qu'une boîte d'alerte apparaît.
  5. Ouvrir l'inspecteur du navigateur et repérer l'endroit où le commentaire a été inséré dans la page.
  6. Remplacer ensuite l'affichage précédent par une version échappée avec htmlspecialchars().
  7. Recharger la page. Vérifier que la boîte d'alerte n'apparaît plus et que le texte <script>alert('Test XSS')</script> s'affiche à l'écran.
  8. Ouvrir à nouveau l'inspecteur, puis afficher le code source de la page dans le navigateur. Comparer ce que le navigateur interprète avec ce qui a été envoyé dans le HTML.

Réaliser cet exercice uniquement dans un projet de démonstration local.

Exo-02 — PHP dans le HTML

Cet exercice consiste à créer une page PHP unique qui mélange logique et affichage HTML. L'objectif est de pratiquer la syntaxe alternative (if/endif, foreach/endforeach), le raccourci <?= ?>, l'opérateur ternaire, l'utilisation de htmlspecialchars() au bon endroit et la bonne pratique de séparation logique/affichage.

Dans cet exercice, la variable $utilisateur, le tableau $langages et le tableau $produits simulent des données provenant d'une base de données ou d'une API. Lorsqu'une de ces valeurs est affichée dans le HTML, il faut donc l'échapper avec htmlspecialchars(). En revanche, les textes que vous produisez vous-même dans le code, comme En stock ou Rupture, n'ont pas besoin d'être échappés ici.

Données fournies

Utiliser les données suivantes dans la partie logique du fichier


                    <?php
                    $utilisateur = "Alice";
                    $estConnecte = true;

                    $langages = ["PHP", "JavaScript", "Python", "Java", "C#"];

                    $produits = [
                        ['nom' => 'Clavier mécanique', 'prix' => 89.99, 'enStock' => true],
                        ['nom' => 'Souris ergonomique', 'prix' => 54.50, 'enStock' => true],
                        ['nom' => 'Écran 27 pouces',   'prix' => 329.00, 'enStock' => false],
                        ['nom' => 'Casque audio',      'prix' => 74.95, 'enStock' => true],
                        ['nom' => 'Webcam HD',         'prix' => 42.00, 'enStock' => false],
                    ];
                    ?>
                

Instructions

  1. Rendez-vous dans le fichier exo-02.php. Commencez par importer le fichier config.php en haut du fichier afin de rendre la constante BASE_URL disponible. Définissez ensuite la variable $pageTitre, puis incluez header.php avant d'écrire le contenu de la page. À la fin du fichier, incluez footer.php.
  2. Placer toute la logique de l'exercice en haut du fichier, avant tout HTML.
  3. Dans la partie HTML, afficher un message de bienvenue conditionnel.
    • Si $estConnecte vaut true, afficher <p>Bienvenue, Alice !</p> en utilisant la variable $utilisateur.
    • Sinon, afficher <p>Veuillez vous connecter.</p>.
    • Utiliser la syntaxe alternative if/else/endif.
    • Échapper avec htmlspecialchars() la valeur provenant de $utilisateur.
  4. Afficher la liste des langages dans une liste <ul>.
    • Parcourir le tableau $langages avec foreach/endforeach.
    • Chaque langage doit apparaître dans un élément <li>.
    • Échapper chaque nom de langage avec htmlspecialchars().
  5. Afficher les produits dans une liste HTML <ul>.
    • Chaque produit doit apparaître dans un élément <li>.
    • Dans chaque élément, afficher le nom du produit, son prix et son état de disponibilité.
    • Échapper avec htmlspecialchars() le nom du produit et son prix.
    • Pour la disponibilité, utiliser un opérateur ternaire afin d'afficher En stock avec un style vert ou Rupture avec un style rouge, selon la valeur de enStock.
    • Vous pouvez par exemple produire une structure de ce type
      
                                          <ul>
                                              <li>
                                                  <h3>Clavier mécanique</h3>
                                                  <p>Prix 89.99 €</p>
                                                  <p class="disponible">En stock</p>
                                              </li>
                                          </ul>
                                      
  6. Tester la page dans le navigateur. Modifier ensuite la valeur de $estConnecte à false et recharger la page pour vérifier que le message de bienvenue change.

Exo-03 — Mise en mémoire tampon

Cet exercice consiste à créer des fonctions qui construisent du HTML à l'aide de ob_start() et ob_get_clean(), puis à les utiliser dans une page en respectant la séparation logique/affichage.

Dans cet exercice, les données fournies simulent elles aussi des informations provenant d'une base de données ou d'une API. Même si elles sont écrites directement dans le fichier pour simplifier l'exercice, elles doivent être traitées comme des données externes au HTML. Les valeurs affichées reçues dans les paramètres des fonctions doivent donc être échappées avec htmlspecialchars().

Données fournies

Utiliser les données suivantes dans la partie logique du fichier


                    <?php
                    $services = [
                        ['nom' => 'Hébergement Web',        'prix' => '4.99 €/mois'],
                        ['nom' => 'Nom de domaine .be',     'prix' => '8.50 €/an'],
                        ['nom' => 'Certificat SSL',         'prix' => 'Gratuit'],
                        ['nom' => 'Sauvegarde quotidienne', 'prix' => '2.00 €/mois'],
                    ];
                    ?>
                

Instructions

  1. Rendez-vous dans le fichier exo-03.php. Commencez par importer le fichier config.php en haut du fichier afin de rendre la constante BASE_URL disponible. Définissez ensuite la variable $pageTitre, puis incluez header.php avant d'écrire le contenu de la page. À la fin du fichier, incluez footer.php.
  2. Créer une fonction genererAlerte(string $message, string $type): string.
    • Le paramètre $type peut valoir "succes", "erreur" ou "info".
    • La fonction retourne un bloc HTML <div> dont la classe CSS correspond au type choisi.
    • Utiliser ob_start() pour ouvrir la mémoire tampon, écrire le HTML normalement, puis retourner le résultat avec ob_get_clean().
    • Échapper le message avec htmlspecialchars().
    • Utiliser le paramètre $type uniquement pour choisir, dans votre propre code, une classe CSS parmi les trois valeurs prévues par l'exercice.
  3. Créer une fonction genererListeServices(array $services): string.
    • La fonction reçoit un tableau de services. Chaque service possède un nom et un prix.
    • La fonction retourne une liste HTML <ul> où chaque élément <li> affiche le nom suivi du prix.
    • Utiliser ob_start(), la syntaxe alternative foreach/endforeach à l'intérieur du tampon, puis retourner le résultat avec ob_get_clean().
    • Échapper le nom et le prix avec htmlspecialchars().
  4. Dans la partie logique du fichier, appeler les fonctions et stocker les résultats dans des variables.
    • Générer trois alertes de types différents avec des messages de votre choix.
    • Générer la liste des services à partir du tableau $services fourni.
  5. Dans la partie affichage, afficher chaque variable avec <?= ?>. Vérifier dans le navigateur que les alertes et la liste s'affichent correctement.

Projet Progressif 01 - Bonus : Menu Dynamique

Cet exercice fait suite au Projet Progressif 01 du chapitre précédent. L'objectif est de dynamiser le menu de navigation en mettant automatiquement en évidence le lien correspondant à la page actuellement affichée, puis de refactoriser ce menu dans une fonction réutilisable.

Attendu

À la fin de cet exercice, le menu de navigation du projet doit appliquer automatiquement une classe CSS active au lien correspondant à la page en cours. Cette logique doit être encapsulée dans une fonction réutilisable.

Instructions

  1. Dans le menu de navigation du fichier header.php, il est courant de modifier l'apparence du lien correspondant à la page active. Généralement, on ajoute une classe CSS à l'élément <li> contenant le lien actif. Par exemple, si l'utilisateur se trouve sur la page "Tarifs"
    
                                <nav>
                                    <ul>
                                        <li><a href="...">Accueil</a></li>
                                        <li class="active"><a href="...">Tarifs</a></li>
                                        <li><a href="...">Contact</a></li>
                                    </ul>
                                </nav>
                            
  2. Pour identifier la page actuellement affichée, PHP met à votre disposition la variable superglobale $_SERVER contenant des informations sur la requête HTTP en cours. Afficher le contenu de cette variable sur l'une de vos pages pour repérer la clé la plus adaptée
    
                                <?php
                                echo '<pre>';
                                print_r($_SERVER);
                                echo '</pre>';
                                ?>
                            

    Les balises <pre> (preformatted text) demandent au navigateur de respecter les espaces, les tabulations et les retours à la ligne tels qu'ils apparaissent dans le code source. Par défaut, le HTML ignore ces caractères d'espacement et les réduit à un simple espace. Comme print_r() produit une sortie indentée avec des retours à la ligne, les balises <pre> sont indispensables pour obtenir un affichage lisible dans le navigateur.

  3. En explorant $_SERVER, vous remarquerez que plusieurs clés semblent contenir des informations similaires. Voici les principales et leurs différences :

    • REQUEST_URI : l'URI telle que demandée par le navigateur, incluant les éventuels paramètres. Par exemple /mon-site/contact.php?id=5 ou /mon-site/.
    • SCRIPT_NAME : le chemin du script exécuté, sans les paramètres. Par exemple /mon-site/contact.php ou /mon-site/index.php.
    • PHP_SELF : similaire à SCRIPT_NAME, mais peut contenir des informations de chemin supplémentaires. Présente un risque de sécurité si elle est affichée sans précaution.
    • SCRIPT_FILENAME : le chemin absolu du fichier sur le disque (par exemple C:/laragon/www/mon-site/contact.php). Malgré son nom trompeur, cette clé n'a rien à voir avec l'URL.

    La clé la plus adaptée est REQUEST_URI, car sa valeur correspond à ce qu'on écrit dans les attributs href du menu. À l'inverse, SCRIPT_NAME retournerait /mon-site/index.php pour la page d'accueil, ce qui ne correspondrait pas au lien /mon-site/ de notre menu.

    Cependant, REQUEST_URI peut contenir des paramètres d'URL (par exemple /mon-site/contact.php?sujet=info), ce qui ferait échouer la comparaison. Pour ne récupérer que le chemin, utiliser la fonction parse_url()

    
                                $pageActuelle = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
                            

    La fonction parse_url() découpe une URL en ses différentes composantes. En lui passant la constante PHP_URL_PATH en deuxième argument, on lui demande de ne retourner que le chemin, en ignorant les paramètres et tout le reste.

  4. Utiliser cette valeur pour comparer chaque lien du menu avec la page en cours. Ajouter dynamiquement la classe active à l'élément <li> correspondant. Vous pouvez utiliser la syntaxe alternative (if/endif) ou un opérateur ternaire. N'oubliez pas que vos liens incluent BASE_URL, et que la valeur retournée par parse_url() le contiendra également.
  5. Tester le menu en naviguant entre les pages. Vérifier que la classe active est bien appliquée au bon lien.
  6. Refactoriser le menu dans une fonction réutilisable.
    • Créer une fonction qui prend en paramètre un tableau associatif des liens (chaque élément contient un label et une URL) et retourne le HTML du menu complet, avec la classe active appliquée automatiquement au lien correspondant à la page en cours.
    • Utiliser ob_start() et ob_get_clean() pour construire le HTML à l'intérieur de la fonction, et la syntaxe alternative foreach/endforeach pour parcourir les liens.

    Données pour le tableau des liens

    
                                <?php
                                $menuLiens = [
                                    ['label' => 'Accueil',  'url' => BASE_URL . '/'],
                                    ['label' => 'Contact',  'url' => BASE_URL . '/contact.php'],
                                ];
                                ?>
                            
  7. Remplacer le menu statique dans header.php par un appel à cette fonction. Tester à nouveau la navigation pour vérifier que tout fonctionne.