Le problème : HTTP est sans mémoire
Chaque requête HTTP est indépendante. Le serveur ne sait pas que la personne qui visite la page 2 est la même que celle qui était sur la page 1. C'est comme si chaque fois que vous ouvriez une porte dans le bâtiment, la plomberie oubliait qui vous êtes.
Les sessions et les cookies résolvent ce problème en créant une mémoire entre les pages.
Les sessions : mémoire côté serveur
Une session stocke des données sur le serveur, liées à un visiteur via un identifiant unique :
// TOUJOURS en première ligne du fichier (avant tout HTML)
session_start();
// Stocker des données
$_SESSION['utilisateur'] = 'Alice';
$_SESSION['role'] = 'admin';
$_SESSION['connecte'] = true;
// Lire des données (sur une autre page)
session_start();
echo $_SESSION['utilisateur']; // → Alice
// Supprimer une donnée
unset($_SESSION['role']);
// Détruire toute la session (déconnexion)
session_destroy();
Important : session_start() doit être appelé avant tout output HTML, sinon PHP affiche une erreur « headers already sent ».
Les cookies : mémoire côté navigateur
Un cookie est un petit fichier stocké dans le navigateur de l'utilisateur :
// Créer un cookie (expire dans 30 jours)
setcookie("theme", "dark", time() + (30 * 24 * 3600), "/");
// Lire un cookie
$theme = $_COOKIE['theme'] ?? 'light';
echo "Thème actuel : $theme";
// Supprimer un cookie (date dans le passé)
setcookie("theme", "", time() - 3600, "/");
Sessions vs Cookies :
- Session — données sur le serveur, disparaît à la fermeture du navigateur
- Cookie — données sur le navigateur, peut durer des jours/mois
Règle : les données sensibles (login, rôle, ID) vont en session. Les préférences (thème, langue) vont en cookie.
Exemple : flux de connexion
// login.php
session_start();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$email = $_POST['email'] ?? '';
$password = $_POST['password'] ?? '';
// Vérifier en base de données (simplifié ici)
if ($email === 'alice@exemple.fr' && password_verify($password, $hash_stocke)) {
// Connexion réussie
$_SESSION['user_id'] = 42;
$_SESSION['user_nom'] = 'Alice';
session_regenerate_id(true); // Sécurité !
header('Location: /dashboard.php');
exit;
} else {
$erreur = "Email ou mot de passe incorrect.";
}
}
// dashboard.php
session_start();
if (empty($_SESSION['user_id'])) {
header('Location: /login.php');
exit;
}
echo "Bienvenue, " . htmlspecialchars($_SESSION['user_nom']);
// logout.php
session_start();
$_SESSION = [];
session_destroy();
header('Location: /login.php');
Sécurité des sessions
session_regenerate_id(true)— après le login, pour éviter le « session fixation »- Cookies HttpOnly — empêche JavaScript d'accéder au cookie de session
- Cookies Secure — le cookie n'est envoyé qu'en HTTPS
- SameSite=Strict — protège contre les attaques CSRF
// Configuration sécurisée des cookies de session
ini_set('session.cookie_httponly', 1);
ini_set('session.cookie_secure', 1);
ini_set('session.cookie_samesite', 'Strict');
session_start();
// Ou avec setcookie() pour vos propres cookies
setcookie("theme", "dark", [
'expires' => time() + 86400 * 30,
'path' => '/',
'httponly' => true,
'secure' => true,
'samesite' => 'Strict'
]);
The problem: HTTP is stateless
Each HTTP request is independent. The server doesn't know that the person visiting page 2 is the same one who was on page 1. It's as if every time you opened a door in the building, the plumbing forgot who you are.
Sessions and cookies solve this problem by creating memory between pages.
Sessions: server-side memory
A session stores data on the server, linked to a visitor via a unique ID:
// ALWAYS on the first line (before any HTML)
session_start();
// Store data
$_SESSION['user'] = 'Alice';
$_SESSION['role'] = 'admin';
$_SESSION['logged_in'] = true;
// Read data (on another page)
session_start();
echo $_SESSION['user']; // → Alice
// Delete a value
unset($_SESSION['role']);
// Destroy the entire session (logout)
session_destroy();
Important: session_start() must be called before any HTML output, otherwise PHP shows a "headers already sent" error.
Cookies: browser-side memory
A cookie is a small file stored in the user's browser:
// Create a cookie (expires in 30 days)
setcookie("theme", "dark", time() + (30 * 24 * 3600), "/");
// Read a cookie
$theme = $_COOKIE['theme'] ?? 'light';
echo "Current theme: $theme";
// Delete a cookie (date in the past)
setcookie("theme", "", time() - 3600, "/");
Sessions vs Cookies:
- Session — data on the server, disappears when browser closes
- Cookie — data in the browser, can last days/months
Rule: sensitive data (login, role, ID) goes in sessions. Preferences (theme, language) go in cookies.
Example: login flow
// login.php
session_start();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$email = $_POST['email'] ?? '';
$password = $_POST['password'] ?? '';
// Check database (simplified here)
if ($email === 'alice@example.com' && password_verify($password, $stored_hash)) {
// Login successful
$_SESSION['user_id'] = 42;
$_SESSION['user_name'] = 'Alice';
session_regenerate_id(true); // Security!
header('Location: /dashboard.php');
exit;
} else {
$error = "Invalid email or password.";
}
}
// dashboard.php
session_start();
if (empty($_SESSION['user_id'])) {
header('Location: /login.php');
exit;
}
echo "Welcome, " . htmlspecialchars($_SESSION['user_name']);
// logout.php
session_start();
$_SESSION = [];
session_destroy();
header('Location: /login.php');
Session security
session_regenerate_id(true)— after login, to prevent "session fixation"- HttpOnly cookies — prevents JavaScript from accessing the session cookie
- Secure cookies — cookie only sent over HTTPS
- SameSite=Strict — protects against CSRF attacks
// Secure session cookie configuration
ini_set('session.cookie_httponly', 1);
ini_set('session.cookie_secure', 1);
ini_set('session.cookie_samesite', 'Strict');
session_start();
// Or with setcookie() for your own cookies
setcookie("theme", "dark", [
'expires' => time() + 86400 * 30,
'path' => '/',
'httponly' => true,
'secure' => true,
'samesite' => 'Strict'
]);
Copiez ce prompt dans Claude ou ChatGPT :
Crée un système de panier d'achat en PHP avec sessions : ajouter un produit, supprimer un produit, afficher le total. Utilise $_SESSION['panier'] comme tableau associatif.
session_regenerate_id(true) ?