Architecture d'un site web, première partie —
Squelettes de pages en PHP

Alexandre Niveau
GREYC — Université de Caen

Pages d'un site web

Généralement : éléments communs à toutes les pages, typiquement
  • bannière
  • menu
  • pied de page…
Le reste change de page en page.

De plus, le contenu de l'élément head est (pratiquement) le même sur chaque page

Recopier le contenu commun dans le fichier HTML de chaque page ⇒ non-respect du principe DRY (don't repeat yourself)

Maintenance de plusieurs pages HTML

Même sur un minuscule site avec une poignée de pages, le non-respect de DRY pose des problèmes de maintenance
Toute modification
  • des méta-données (feuilles de style…)
  • des éléments communs (bannière, menu…)
  • de la structure de la page
est rendue fastidieuse et risque d'introduire des incohérences.

Meilleure solution : séparer parties communes et parties spécifiques à chaque page

Exemple très simple

Site des poèmes (archive du code) : sur les cinq pages, seul le contenu du bloc #principal change

Le reste constitue le squelette de la page

Chaque fichier HTML contient, dans l'ordre :
  • le début du squelette
  • le bloc #principal (texte de la page d'accueil ou photo+poème)
  • la fin du squelette

Modifier le nom de la feuille de style, le menu, et la structure de la page est fastidieux et risqué

Solution simpliste

Une possibilité : séparer squelette et contenu unique de chaque page…

… et générer les fichiers HTML à partir de ces éléments, avant de les mettre en ligne

Pour le site des poèmes, on pourra avoir les fichiers On a choisi d'appeler les fichiers .frg.html, pour mettre en évidence le fait que ce sont des fragments de fichiers HTML, qui n'ont pas de sens pris isolément

NB: on prend soin d'organiser ses fichiers dans des répertoires distincts, en l'occurrence squel pour les fragments de squelette et contenu pour les fragments de contenu

Génération des fichiers HTML

On va utiliser ces fragments pour générer les fichiers HTML dans le répertoire site, qui va contenir le résultat final, c'est-à-dire le site à déployer sur le serveur web

Le répertoire site contient déjà le CSS et les images

archive du code dans cet état de départ

Pour chaque page, il faut simplement concaténer le début de squelette, le contenu de la page et la fin du squelette, et écrire tout ça dans un fichier HTML dans le répertoire site

Par exemple pour la page du poème « Ma Bohème », il suffit d'utiliser la commande
cat squel/debut.frg.html contenu/boheme.frg.html squel/fin.frg.html >site/boheme.html

Script de génération

Plutôt que de répéter les commandes pour chaque page après chaque modification, on va écrire un script generer.sh :
#!/bin/sh
cat squel/debut.frg.html contenu/index.frg.html squel/fin.frg.html >site/index.html
cat squel/debut.frg.html contenu/boheme.frg.html squel/fin.frg.html >site/boheme.html
cat squel/debut.frg.html contenu/automne.frg.html squel/fin.frg.html >site/automne.html
…
ou plus proprement (DRY) :
#!/bin/sh
for page in boheme correspondances bois automne index
do
    cat squel/debut.frg.html contenu/"$page".frg.html squel/fin.frg.html >site/"$page".html
done

Il ne reste plus qu'à déployer le répertoire site (on peut aussi faire un script qui génère le HTML puis déploie le site — attention cependant à bien le tester avant de l'utiliser, la catastrophe est vite arrivée…)

N.B.: on ne met pas les répertoires contenu et squel sur le serveur — seulement les fichiers HTML « finalisés ».

Résultat et archive du code

Limites de cette approche

Ne fonctionne que si toutes les pages ont exactement le même « début » et la même « fin »

impossible de faire varier le titre des pages (title dans le head), par exemple pour mettre le titre du poème

Les fragments des poèmes ont la même structure ⇒ beaucoup d'éléments communs (en particulier au niveau de la figure)

si on veut changer cette structure, même problème qu'au départ

Pour résoudre ces problèmes : un programme de génération de pages moins basique suffirait

Limite d'un site statique

Notre approche marcherait même avec des milliers de pages, mais dans ce cas le site serait inutilisable : l'internaute a besoin d'outils pour manipuler les pages (recherche, tri…)

on aura besoin d'une base de données contenant les poèmes et leurs caractéristiques (titre, auteur, date de publication…)

On ne peut alors plus se contenter d'un site statique, c'est-à-dire un ensemble de fichiers HTML écrits par le webmestre et directement placés sur le serveur

il va falloir que le serveur construise les pages dynamiquement, à partir de la base de données, en fonction des requêtes des internautes

Pages web dynamiques

Page web dynamique = le serveur a généré le HTML à la demande

Exemple :
  • le client demande la page toto.truc
  • le serveur n'a pas de page HTML toto.truc : il sait que cette page doit être générée en lançant un certain programme
  • il lance le programme et récupère en sortie une page HTML
  • il envoie le HTML ainsi généré au client

Le client ne sait pas tout ça : il a demandé une page et a obtenu du HTML. Il n'a aucun moyen de savoir que la page a été générée dynamiquement.

Langages de génération de HTML

  • On peut utiliser n'importe quel langage côté serveur !
  • Il faut juste que le serveur sache lancer le programme quand il reçoit les requêtes correspondantes
  • Exemple : on a configuré le serveur pour qu'il exécute ce script quand quelqu'un demande la page pagedynamique.html (qui n'existe pas en tant que fichier, comme on peut le voir)
  • Langages généralistes souvent utilisés : Java, Ruby, Perl, Python…
  • Langages prévus expressément pour cet usage : PHP, ASP.NET (Microsoft)
  • … mais rien n'empêche d'utiliser autre chose (C, C++… assembleur, shell !…)

PHP

Dans le cadre de ce cours, et dans toute la licence pro, on utilisera le langage PHP

Langage de script, comme Python ou bash

Spécialement conçu pour les sites web (architecture client/serveur)

Idée de départ : rendre « simple » la réalisation de sites web dynamiques en permettant d'inclure des instructions dans le code HTML (en pratique, très souvent mal utilisé)

Pas le meilleur langage de programmation, mais toujours très utilisé, notamment par les principaux CMS (WordPress, Drupal, Joomla)

Exemple de script PHP

<!DOCTYPE html>
<html>
<head><title>Ma page</title><meta charset="UTF-8" /></head>
<body>
    <h2>Les nombres</h2>
    <p>Voici les nombres de 1 à 10000 :

        <?php
            
for ($i 1$i <= 10000$i++) {
                echo 
"$i, ";
            }
        
?>

    </p>
</body>
</html>
Résultat

C'est une page HTML avec des blocs d'instructions encadrées par <?php et ?>

Ce qui est en dehors de ces blocs est affiché tel quel

Les blocs sont remplacés par le résultat de l'exécution des instructions

Regarder le code source de la page : noter qu'il ne subsiste aucune trace du code PHP !

Que s'est-il passé ?

Déroulement :
  • Le navigateur demande au serveur la page nombres.php
  • Le serveur voit qu'il s'agit d'un script PHP : il appelle l'interpréteur PHP sur le script nombres.php
  • L'interpréteur exécute le script, ce qui génère une page HTML
    • Ce qui est en dehors des blocs PHP est reproduit tel quel
    • Les blocs PHP sont remplacés par le résultat de l'exécution des instructions
  • La page HTML générée est renvoyée au navigateur

Le navigateur ne voit jamais le code PHP : il ne récupère que de l'HTML !

Variables et instruction echo

PHP permet d'utiliser des variables. Elles commencent toujours par le caractère $.

Elles permettent par exemple de stocker un contenu pour éviter de le répéter

L'instruction echo permet d'afficher une variable ou une chaîne de caractères

<?php
$titre 
"Page démo";
$contenu "Le contenu sera généré par mon programme";
?>
<!DOCTYPE html>
<html lang="fr">
<head>
    <title><?php echo $titre?></title>
</head>
<body>
    <h1><?php echo $titre?></h1>
    <p><?php echo $contenu?></p>
</body>
</html>
Résultat
Regarder le code source de la page dans le navigateur : le premier bloc d'instructions a disparu (il ne génère aucune sortie), mais il a bien été exécuté puisque les variables ont la bonne valeur.

À quoi sert PHP ?

Pour le navigateur, ça ne change rien : le résultat est toujours de l'HTML

Mais une page web en PHP est beaucoup plus puissante qu'une page web purement HTML/CSS :
  • utilisation de variables et de boucles
  • utilisation d'informations stockées dans une base de données
  • utilisation d'informations fournies par l'internaute

PHP permet de construire des sites dynamiques, par opposition aux sites statiques n'utilisant qu'HTML/CSS.

Retour sur les poèmes

On va reprendre exactement le même principe que précédemment, mais cette fois on va assembler les morceaux dynamiquement, côté serveur, avec PHP

On garde les mêmes répertoires squel (avec les fragments de squelette) et contenu (avec les fragments de contenu), mais cette fois ils seront placés sur le serveur (puisque les pages seront assemblées dynamiquement)

On crée un fichier PHP par page :
  • index.php pour la page d'accueil
  • boheme.php pour la page de « Ma Bohème »
  • etc.

Aucun de ces fichiers ne contiendra de HTML : il assemblera les deux fragments de squelette avec le bon fragment de contenu

Fonction include

La fonction PHP include permet d'inclure un fichier.

Par exemple, si le fichier toto.frg.html contient
<p><code>toto</code> est une <em>variable
métasyntaxique</em> utilisée dans les
exemples de programmes.</p>
alors le script PHP suivant
<h1>Toto</h1>
<?php include("toto.frg.html"); ?>
<footer>Copyright Toto</footer>
donnera comme résultat
<h1>Toto</h1>
<p><code>toto</code> est une <em>variable
métasyntaxique</em> utilisée dans les
exemples de programmes.</p>
<footer>Copyright Toto</footer>

Utilisation de include

Pour chaque page, on a juste besoin
  • d'inclure le début du squelette
  • d'inclure le fragment de contenu
  • d'inclure la fin du squelette
Le code de la page boheme.php sera donc par exemple simplement :
<?php
include("squel/debut.frg.html");
include(
"contenu/boheme.frg.html");
include(
"squel/fin.frg.html");
?>

Résultat et archive du code

Intérêt ?

Pour l'instant, on n'a rien gagné par rapport à la version statique… (On a même plutôt perdu, puisqu'on fait faire du travail en plus au serveur à chaque fois que quelqu'un accède au site)

Mais on peut aussi utiliser include pour inclure du code PHP

On peut alors exploiter les variables pour rendre notre squelette plus flexible

Utilisation de include sur un fichier PHP

Par exemple, si le fichier texte.php contient
<p><code><?php echo $variable?></code>
est une <em>variable
métasyntaxique</em> utilisée dans les
exemples de programmes.</p>
alors le script PHP suivant
<h1>Des variables</h1>
<?php
    $variable 
"toto";
    include(
"texte.php");
    
$variable "titi";
    include(
"texte.php");
?>
<footer>Copyright Toto</footer>
sera exactement équivalent au script
<h1>Des variables</h1>
<?php
    $variable 
"toto";
?>
<p><code><?php echo $variable?></code>
est une <em>variable
métasyntaxique</em> utilisée dans les
exemples de programmes.</p>
<?php
    $variable 
"titi";
?>
<p><code><?php echo $variable?></code>
est une <em>variable
métasyntaxique</em> utilisée dans les
exemples de programmes.</p>
<footer>Copyright Toto</footer>
c'est-à-dire que le résultat sera
<h1>Des variables</h1>
<p><code>toto</code> est une <em>variable
métasyntaxique</em> utilisée dans les
exemples de programmes.</p>
<p><code>titi</code> est une <em>variable
métasyntaxique</em> utilisée dans les
exemples de programmes.</p>
<footer>Copyright Toto</footer>

En quelque sorte, le script courant s'interrompt pour exécuter le script inclus

Un vrai squelette de page avec des variables

On va pouvoir rendre notre squelette plus flexible

changer .frg.html en .frg.php

En premier lieu, on peut utiliser une variable pour que l'élément title soit adapté à la page

On peut aussi maintenant faire un fragment de squelette qui affiche un poème, avec pour variables le titre, l'auteur, la photo et le texte

Voir démos pendant le cours

chaque page de poème inclut les trois morceaux ⇒ faire un seul include avec un squelette

Résultat final pour les poèmes

Le résultat final du site des poèmes est dans cette archive (et visible ici, mais la différence avec les précédents est très minime)

En particulier, le squelette des pages de poèmes est le suivant :
<?php
include("fragments/debut.frg.php");
?>
<figure class="photo">
    <img src="images/<?php echo $image?>" alt="Photo de <?php echo $auteur?>" />
    <figcaption><?php echo $auteur?></figcaption>
</figure>

<article class="poeme">
<h1><?php echo $titre?></h1>

    <?php echo $texte?>

    <div class="signature"><?php echo $auteur?><?php echo $infos_publication?></div>
</article>

<?php
include("fragments/fin.frg.php");
?>
et la page de « Ma Bohème » :
<?php
$titre 
"Ma bohème";
$auteur "Arthur Rimbaud";
$image "rimbaud.jpg";
$infos_publication 'publié en octobre 1870';
$texte "
    <p>Je m’en allais, les poings dans mes poches crevées&nbsp;;<br />
    Mon paletot aussi devenait idéal&nbsp;;<br />
    J’allais sous le ciel, Muse&nbsp;! et j’étais ton féal&nbsp;;<br />
    Oh&nbsp;! là là&nbsp;! que d’amours splendides j’ai rêvées&nbsp;!</p>

    <p>Mon unique culotte avait un large trou.<br />
    — Petit Poucet rêveur, j’égrenais dans ma course<br />
    Des rimes. Mon auberge était à la Grande-Ourse&nbsp;;<br />
    — Mes étoiles au ciel avaient un doux frou-frou.</p>

    <p>Et je les écoutais, assis au bord des routes,<br />
    Ces bons soirs de septembre où je sentais des gouttes<br />
    De rosée à mon front, comme un vin de vigueur&nbsp;;</p>

    <p>Où, rimant au milieu des ombres fantastiques,<br />
    Comme des lyres, je tirais les élastiques<br />
    De mes souliers blessés, un pied près de mon cœur&nbsp;!</p>
"
;

include(
"squel/poeme.squel.php");
?>

NB: on en a profité pour mieux organiser les fichiers du site. Très important, on en reparlera.

Conclusion partielle

On a déjà énormément factorisé le code et séparé la structure du contenu

Il reste encore des problèmes ; en particulier l'architecture n'est toujours pas adaptée à un contenu dynamique (on est obligé d'avoir une page PHP par page réelle du site)