Informatique

Le langage PHP et ses applications

Né en 1994 comme une petite boîte à outils pour une page personnelle, PHP fabrique aujourd'hui une grande partie des pages du Web, de WordPress à Wikipédia. Cinq planches pour comprendre comment il travaille, côté serveur, jusqu'à un petit interpréteur PHP qui tourne dans cette page et dont chaque exemple a été vérifié contre le vrai PHP 8.3.

Un langage qui s'exécute sur le serveur

En 1994, le programmeur dano-canadien Rasmus Lerdorf écrit quelques programmes pour suivre les visites de son CV en ligne : les Personal Home Page Tools. Il les publie en 1995 ; l'idée plaît, et en 1997-1998 deux étudiants israéliens, Andi Gutmans et Zeev Suraski, réécrivent le cœur du langage, rebaptisé PHP : Hypertext Preprocessor. Son principe est simple : on écrit une page HTML dans laquelle on glisse des instructions entre <?php et ?>. Le serveur exécute ces instructions et n'envoie au navigateur que le HTML produit ; le visiteur ne voit jamais le code PHP.

Selon W3Techs (27-28 octobre 2026), PHP est le langage côté serveur de 69,2 % des sites web dont on connaît le langage, et WordPress, écrit en PHP, fait fonctionner 39,6 % de tous les sites. À droite, la répartition des versions de PHP en service.
Planche 1

Requête et réponse : ce qui se passe quand on ouvre une page PHP

Le navigateur envoie une requête HTTP au serveur, avec éventuellement des paramètres dans l'adresse (après le ?). Le serveur web confie le fichier .php à l'interpréteur PHP, qui l'exécute de haut en bas : le HTML est recopié tel quel, les morceaux PHP sont remplacés par ce qu'ils affichent. La page fabriquée revient au navigateur dans la réponse HTTP. Choisissez les paramètres puis envoyez la requête.

7
Le voyage d'une requête : le navigateur, le serveur web et l'interpréteur PHP. Le paquet bleu est la requête, le vert la réponse.

Le fichier bonjour.php sur le serveur

Requête HTTP envoyée


      

HTML reçu par le navigateur

Ce que le visiteur voit

Octets du fichier PHP / de la page envoyée
—
Contrôle : sortie du vrai PHP 8.3 pour ces paramètres (date mise à part)
—
Ce qu'il faut retenir. Le code PHP ne quitte jamais le serveur : le navigateur reçoit du HTML ordinaire, différent à chaque requête puisqu'il dépend des paramètres et de la date. C'est ce qu'on appelle une page dynamique, par opposition à un fichier HTML statique. Remarquez htmlspecialchars : avec le prénom « <b>Pirate</b> », les chevrons sont transformés en &lt; et &gt; et s'affichent au lieu d'être interprétés. Sans cette précaution, un visiteur pourrait glisser son propre code dans la page (planche 3).
Planche 2

Les tableaux de PHP : une table de hachage qui se souvient de l'ordre

En PHP, un seul type, le array, sert à la fois de liste et de dictionnaire : $capitale['France'] = 'Paris'. Pour retrouver très vite une clé, PHP la transforme en nombre par une fonction de hachage, puis range l'élément dans le compartiment (en anglais bucket) désigné par ce nombre. Pour les clés de texte, PHP utilise la fonction DJBX33A de Daniel J. Bernstein : partir de 5381, puis pour chaque caractère multiplier par 33 et ajouter son code. En plus, PHP garde les éléments dans l'ordre où on les a ajoutés : c'est l'ordre que suit foreach.

Les compartiments (à gauche, numérotés) et les clés qui y sont rangées, en chaîne quand plusieurs tombent au même endroit. Le tableau double de taille quand il est plein.

Calcul du hachage de la dernière clé


      

Ordre de foreach (ordre d'insertion)

—

Éléments / compartiments
—
Plus longue chaîne
—
Comparaisons de clés pour tout insérer (mesurées)
—
Si toutes les clés collisionnent : n(n − 1)/2
—

Le coût d'une attaque, mesuré

Comparaisons nécessaires pour insérer n clés : clés ordinaires (bleu) contre clés fabriquées pour avoir toutes le même hachage (rouge). Échelles logarithmiques.
Ce qu'il faut retenir. Normalement chaque compartiment contient très peu de clés et l'accès est presque immédiat, quelle que soit la taille du tableau. Mais « Ez » et « FY » ont exactement le même hachage (69 × 33 + 122 = 70 × 33 + 89 = 2399), et on peut les combiner : « EzEz », « EzFY », « FYEz »… ont toutes la même valeur. Toutes ces clés s'entassent dans un seul compartiment et chaque insertion doit comparer la nouvelle clé à toutes les précédentes : le travail croît comme n², ce que la mesure confirme exactement. En décembre 2011, deux chercheurs ont montré qu'un seul formulaire rempli de telles clés pouvait occuper un serveur PHP pendant des minutes ; PHP 5.3.9 (janvier 2012) a alors limité à 1 000 le nombre de champs acceptés par requête (max_input_vars).
Planche 3

La sécurité : ne jamais mêler les données au code

Une page PHP reçoit des textes tapés par n'importe qui. Le danger survient quand ces textes sont collés dans du code : une requête SQL envoyée à la base de données, ou une page HTML envoyée au navigateur. Un visiteur malveillant peut alors écrire un texte qui change le sens du code. Ce sont les deux failles les plus célèbres du Web : l'injection SQL et le XSS (cross-site scripting).

Un formulaire de connexion vérifie le nom et le mot de passe en interrogeant la table utilisateurs. Tapez des identifiants, ou essayez les attaques proposées.

Code naïf : concaténation

$sql = "SELECT * FROM utilisateurs
        WHERE nom = '" . $_POST['nom'] . "'
        AND mdp = '" . $_POST['mdp'] . "'";
$res = $db->query($sql);

Requête réellement envoyée

Code sûr : requête préparée

$st = $db->prepare("SELECT * FROM utilisateurs
        WHERE nom = ? AND mdp = ?");
$st->execute([$_POST['nom'], $_POST['mdp']]);

Requête et valeurs, envoyées séparément

La table utilisateurs. Les lignes surlignées sont celles que renvoie la requête naïve. (Dans une vraie application, les mots de passe ne sont jamais stockés en clair, mais sous forme d'empreinte calculée par password_hash.)

Un livre d'or affiche les messages des visiteurs. Écrivez un message contenant des balises HTML.

echo $message;

echo htmlspecialchars($message);

Lignes renvoyées par la requête naïve
—
Lignes renvoyées par la requête préparée
—
Ce qu'il faut retenir. Avec admin' --, l'apostrophe ferme la chaîne et -- transforme la suite en commentaire : la vérification du mot de passe disparaît, et l'on entre sans le connaître. Avec ' OR '1'='1, la condition devient toujours vraie et la base renvoie tous les utilisateurs. La requête préparée envoie le code SQL et les valeurs séparément : quoi que tape le visiteur, cela reste une valeur, jamais du code. Même règle pour le HTML : htmlspecialchars transforme < en &lt;, et la balise s'affiche au lieu de s'exécuter. Ces deux réflexes, apparus tardivement dans l'histoire de PHP (PDO et ses requêtes préparées datent de PHP 5.1, en 2005), font partie de toute formation sérieuse au développement web.
Planche 4

Les sessions : se souvenir d'un visiteur malgré un protocole sans mémoire

HTTP ne garde aucun souvenir : chaque requête arrive comme si c'était la première. Pour qu'un site se rappelle votre panier, PHP utilise les sessions. Au premier passage, session_start() tire au hasard un long identifiant, l'envoie au navigateur dans un cookie nommé PHPSESSID, et ouvre côté serveur un petit fichier à ce nom. À chaque requête suivante, le navigateur renvoie le cookie, et PHP recharge le contenu du fichier dans le tableau $_SESSION.

À gauche les navigateurs et leurs cookies, à droite les fichiers de session du serveur. L'en-tête Cookie voyage avec chaque requête.
Dernier échange
—
Sessions ouvertes sur le serveur
—

Peut-on deviner un identifiant de session ?

L'identifiant compte 32 caractères hexadécimaux, soit 32 × 4 = 128 bits tirés au hasard (le réglage par défaut de PHP).

1 000 000
10⁹
Identifiants possibles : 2¹²⁸
—
Temps moyen pour tomber sur une session ouverte
—
Contrôle : même calcul en nombres entiers exacts (BigInt)
—
Ce qu'il faut retenir. L'identifiant est la seule chose qui relie le navigateur à son panier : effacez le cookie, et le serveur ne vous reconnaît plus, même si le fichier existe encore. Inversement, quiconque possède le cookie est vous pour le site, d'où le vol de session. Deviner un identifiant au hasard est hors de portée, même avec un milliard d'essais par seconde contre un million de sessions ; les vraies attaques volent donc le cookie, par un XSS (planche 3) ou une connexion non chiffrée. C'est pourquoi on marque ce cookie HttpOnly (illisible par JavaScript) et Secure (envoyé seulement en HTTPS).
Planche 5 · signature

Un petit PHP qui tourne dans votre navigateur

Cette page contient un interpréteur PHP écrit en JavaScript : il lit votre programme, le découpe en jetons, construit son arbre syntaxique et l'exécute. Il reproduit les règles de PHP 8 sur un large sous-ensemble du langage : variables, chaînes avec interpolation, tableaux associatifs, boucles, fonctions, fonctions fléchées, match, mélange de HTML et de PHP, et une centaine de fonctions prédéfinies. Chaque exemple a été exécuté par le vrai PHP 8.3 au moment de la fabrication de cette page : la sortie de référence est enregistrée et comparée en direct, caractère par caractère.

Jetons / étapes d'exécution
—
Octets produits
—
Contrôle : comparaison avec la sortie du vrai PHP 8.3
—
Ce qu'il faut retenir. L'exemple « Les pièges des types » montre la personnalité de PHP : il convertit les valeurs tout seul, "5" + 3 vaut 8 mais "5" . 3 vaut "53", et echo affiche 0.1 + 0.2 comme 0.3 alors que la valeur stockée est 0.30000000000000004. PHP 8 a corrigé plusieurs de ces pièges ("abc" == 0 est désormais faux) et ajouté des types déclarés, comme dans la fonction factorielle(int $n): int. Le vrai PHP compile d'abord le programme en instructions pour sa machine virtuelle (la Zend Engine) et, depuis PHP 8.0, peut même traduire les parties les plus utilisées en code machine (le compilateur JIT). Modifiez les exemples : l'interpréteur signale les erreurs comme PHP, mais il ne gère ni les objets ni les fichiers.

Ce que l'on construit avec PHP

Sites et blogs

WordPress (2003), Drupal, Joomla : les gestionnaires de contenu en PHP font fonctionner une grande partie des sites, des blogs personnels aux sites de journaux et d'institutions.

Encyclopédies et réseaux

Wikipédia repose sur MediaWiki, écrit en PHP. Facebook a commencé en PHP en 2004 et a ensuite créé son propre dialecte, Hack, et sa machine virtuelle HHVM.

Commerce en ligne

PrestaShop (créé à Paris en 2007), WooCommerce, Magento : des boutiques entières, paniers, paiements et stocks, sont écrites en PHP.

Applications métier

Les cadriciels Symfony (créé en France par SensioLabs en 2005) et Laravel (2011) servent à bâtir des applications complètes : intranets, plateformes de formation comme Moodle.

Frise des jalons

Pour aller plus loin

L'interpréteur de la planche 5 est une imitation pédagogique : il calcule sur les nombres comme PHP (entiers et nombres à virgule distincts, affichage à 14 chiffres significatifs), mais ses entiers sont limités à 2⁵³ et il ne connaît pas les objets. Les tables de hachage de la planche 2 sont simplifiées : PHP utilise la même fonction de hachage, mais une organisation de mémoire plus compacte.