Aller au contenu
M07 · C. Manipuler les données

Se souvenir du visiteur : cookies et sessions

Pourquoi HTTP oublie tout entre deux pages, les cookies (setcookie, $_COOKIE, durée, options), les sessions (session_start, $_SESSION, le cookie PHPSESSID), un panier en session, puis un espace membre complet avec connexion, page protégée et déconnexion.

1Situer

Sur Souk Atlas, une cliente se connecte, ajoute un tajine au panier, passe à la page suivante... et le serveur doit encore savoir qui elle est et ce qu'elle a choisi. Or HTTP ne garde aucune mémoire d'une requête à l'autre. Les cookies et les sessions comblent ce manque.

2Comprendre

Session : le jeton côté navigateur, le casier côté serveur
Navigateur cookies PHPSESSID=k3j9f2 / Bonjour Amina Serveur /tmp/ sess_k3j9f2 (vide) utilisateur: id => 1 prenom => Amina role => client fichier supprimé GET / (sans cookie) Set-Cookie: PHPSESSID Cookie: PHPSESSID

Première visite : session_start() ne reçoit aucun cookie. PHP crée une session vide avec un identifiant au hasard.

1 / 5

HTTP oublie tout

Chaque requête HTTP est indépendante : quand le navigateur demande compte.php, le serveur ne sait pas que la même personne vient de remplir le formulaire de connexion.php. On dit que HTTP est sans état. Pour reconnaître un visiteur, il faut qu’il présente quelque chose à chaque requête : un cookie.

Les cookies

<?php
// à faire AVANT tout affichage
setcookie('ville', 'Fès', [
    'expires'  => time() + 30 * 24 * 3600, // 30 jours ; sans expires : jusqu'à la fermeture du navigateur
    'path'     => '/',                     // valable sur tout le site
    'httponly' => true,                    // illisible par JavaScript
    'samesite' => 'Lax',                   // pas envoyé depuis un autre site (sauf simple lien)
]);
echo $_COOKIE['ville'] ?? 'aucune ville connue';

Pour supprimer un cookie, on le renvoie avec une date passée : setcookie('ville', '', time() - 3600, '/').

Les sessions

<?php
session_start();                          // en haut de CHAQUE page qui utilise la session
$_SESSION['ville'] = 'Fès';                // écrire
echo $_SESSION['ville'] ?? '';             // lire
unset($_SESSION['ville']);                 // retirer une valeur

PHP enregistre $_SESSION à la fin du script, dans un fichier comme /tmp/sess_k3j9.... Une session expire après un temps d’inactivité (24 minutes par défaut, réglage session.gc_maxlifetime).

Un espace membre

Le schéma d’une connexion tient en trois pages :

  1. connexion.php : cherche l’utilisateur par son e-mail avec une requête préparée, vérifie le mot de passe avec password_verify (leçon C.5), puis range l’essentiel dans la session et redirige.
  2. Les pages protégées : commencent par vérifier $_SESSION['utilisateur'] et redirigent sinon.
  3. deconnexion.php : vide la session et la détruit.

On ne range jamais le mot de passe dans la session : l’identifiant, le prénom et le rôle suffisent. Et juste après une connexion réussie, on appelle session_regenerate_id(true) : l’identifiant de session change, ce qui déjoue la fixation de session (leçon C.5).

Exemple simple

Le ticket du vestiaire

Au hammam, on laisse ses affaires au vestiaire et on reçoit un jeton numéroté. Le jeton ne contient rien d'autre qu'un numéro ; les affaires restent au vestiaire. Le cookie PHPSESSID est ce jeton, la session est le casier côté serveur.

Exemple simple

Le carnet de fidélité

Le carnet de tampons de l'épicier reste dans votre poche : c'est vous qui le présentez à chaque passage, et vous pourriez y dessiner un faux tampon. Un cookie est stocké chez le visiteur, on ne doit donc jamais lui faire confiance aveuglément.

3Manipuler

Construisez l'espace client : la connexion vérifie le mot de passe dans la base et ouvre la session, la page compte.php est réservée aux clients connectés. Compte d'essai : amina.benali@mail.ma / Atlas2025.
Pas à pas dans le lab ↗ Cliquez sur Exécuter : PHP 8.3 démarre dans votre navigateur (environ 5 Mo à télécharger, une seule fois).

La page s'affichera ici.

Le navigateur demandera /connexion.php au serveur, qui exécutera le PHP et renverra du HTML.

Entre le navigateur et le serveur aucun échange pour l'instant

Consignes 0 / 5

  1. Avec le bon mot de passe : redirection vers compte.php et « Bonjour Amina »
  2. Avec un mauvais mot de passe : « Identifiants incorrects. » et pas de session
  3. compte.php sans être connecté renvoie vers connexion.php
  4. Après la connexion, le navigateur garde le cookie « dernier_email »
  5. Se déconnecter puis revenir sur compte.php renvoie vers la connexion

4Pratiquer

Exercice 1 · Le compteur de visites

Affichez « Vous êtes venu 3 fois » en gardant le nombre de visites dans un cookie valable un an. À la première visite, affichez « Bienvenue ! ».

Voir le corrigé
<?php
$n = (int) ($_COOKIE['visites'] ?? 0) + 1;
setcookie('visites', (string) $n, ['expires' => time() + 365 * 24 * 3600, 'path' => '/', 'httponly' => true, 'samesite' => 'Lax']);
echo $n === 1 ? 'Bienvenue !' : "Vous êtes venu $n fois";

Exercice 2 · Le panier en session

ajouter.php?id=5 ajoute une unité du produit n° 5 au panier rangé dans $_SESSION['panier'] (tableau id => quantité). panier.php affiche le nom, la quantité et le total, en lisant les noms et les prix dans la base.

Voir le corrigé
<?php // ajouter.php
session_start();
$id = (int) ($_GET['id'] ?? 0);
$_SESSION['panier'][$id] = ($_SESSION['panier'][$id] ?? 0) + 1;
header('Location: panier.php');
exit;

<?php // panier.php
session_start();
require __DIR__ . '/db.php';
$panier = $_SESSION['panier'] ?? [];
$total = 0;
if ($panier) {
    $marques = implode(',', array_fill(0, count($panier), '?'));
    $req = $pdo->prepare("SELECT id, nom, prix FROM produits WHERE id IN ($marques)");
    $req->execute(array_keys($panier));
    foreach ($req as $p) {
        $qte = $panier[$p['id']];
        $total += $p['prix'] * $qte;
        echo htmlspecialchars($p['nom']) . " × $qte<br>";
    }
}
echo "Total : $total DH";

Exercice 3 · Réserver l'administration

Écrivez une fonction exigerRole(string $role) à placer en haut des pages d'administration : elle redirige vers connexion.php si personne n'est connecté, et répond 403 « Accès refusé » si le rôle ne correspond pas.

Voir le corrigé
<?php
function exigerRole(string $role): void
{
    if (session_status() !== PHP_SESSION_ACTIVE) session_start();
    $u = $_SESSION['utilisateur'] ?? null;
    if (!$u) {
        header('Location: connexion.php');
        exit;
    }
    if ($u['role'] !== $role) {
        http_response_code(403);
        exit('Accès refusé');
    }
}
exigerRole('admin');

5Vérifier

1. Où sont stockées les données de $_SESSION ?
2. Pourquoi ce code n'envoie-t-il pas le cookie : echo 'Bonjour'; setcookie('ville', 'Fès'); ?
3. Juste après setcookie('ville', 'Fès'), que vaut $_COOKIE['ville'] dans le même script ?