Appelez session_start() en haut d'une page, puis lisez et écrivez $_SESSION['key'] comme n'importe quel tableau : PHP l'enregistre sur le serveur et le retrouve à la requête suivante du visiteur. Pour une petite valeur que le navigateur doit garder, appelez setcookie('name', 'value', time() + 86400) et relisez-la lors des requêtes suivantes dans $_COOKIE['name'].
<?php
session_start(); // before any output
setcookie('theme', 'dark', time() + 60 * 60 * 24 * 30); // 30 days, also before output
$_SESSION['visits'] = ($_SESSION['visits'] ?? 0) + 1;
$theme = $_COOKIE['theme'] ?? 'light'; // set on an earlier visit
echo "You have opened this page {$_SESSION['visits']} times.";
Les sessions et les cookies n'ont de sens qu'à travers plusieurs requêtes HTTP d'un navigateur, donc les exemples qui en ont besoin sont du code simple. La logique autour est du PHP ordinaire sur des tableaux, et cette partie s'exécute ici : dans chaque bloc exécutable, $session remplace $_SESSION, et chaque appel correspond à une requête.
Comment fonctionne une session PHP
- Le premier
session_start()crée un identifiant aléatoire, l'envoie au navigateur dans un cookie nomméPHPSESSID, et vous donne un$_SESSIONvide. - À la fin de la requête, PHP enregistre
$_SESSIONsur le serveur (dans des fichiers par défaut, ou dans Redis, ou une base de données). - À la requête suivante, le navigateur renvoie le cookie,
session_start()lit l'identifiant et charge le tableau enregistré.
Le navigateur ne voit jamais les données, seulement l'identifiant. C'est pourquoi l'identifiant de l'utilisateur connecté va dans $_SESSION et jamais dans un cookie à vous : un visiteur peut modifier ses cookies à volonté, mais pas $_SESSION.
Connecter et déconnecter un utilisateur avec une session
Se connecter, c'est : vérifier le mot de passe, régénérer l'identifiant de session, stocker l'identifiant de l'utilisateur. Se déconnecter, c'est l'inverse, en trois étapes.
<?php
// login.php
session_start();
$user = find_user_by_email($_POST['email'] ?? '');
if ($user && password_verify($_POST['password'] ?? '', $user['password_hash'])) {
session_regenerate_id(true); // new id after login: stops session fixation
$_SESSION['user_id'] = $user['id'];
header('Location: /dashboard.php');
exit;
}
$error = 'Wrong email or password.';
<?php
// any protected page
session_start();
if (!isset($_SESSION['user_id'])) {
header('Location: /login.php');
exit;
}
<?php
// logout.php
session_start();
$_SESSION = []; // 1. forget the data
$p = session_get_cookie_params(); // 2. delete the cookie
setcookie(session_name(), '', time() - 3600, $p['path'], $p['domain'], $p['secure'], $p['httponly']);
session_destroy(); // 3. delete the stored session
header('Location: /');
exit;
session_regenerate_id(true) compte plus qu'il n'y paraît. Si un attaquant peut faire utiliser à une victime un identifiant de session qu'il connaît (par exemple via un lien), et que l'identifiant reste le même après la connexion, l'attaquant est connecté lui aussi. Un nouvel identifiant à la connexion bouche ce trou. La vérification du mot de passe elle-même est expliquée sur la page password_hash.
Faire expirer une session après inactivité
Le nettoyage propre à PHP (session.gc_maxlifetime, 1440 secondes par défaut) s'exécute au hasard et n'est pas une expiration fiable. Stockez l'heure de la dernière requête et vérifiez-la vous-même. Le bloc utilise des timestamps fixes pour que vous voyiez chaque cas ; modifiez $timeout ou les heures.
L'écart de 09:05 à 09:16:40 fait 700 secondes, sous la limite de 15 minutes, donc l'utilisateur reste connecté. L'écart suivant fait 1000 secondes, donc la session est vidée.
Messages flash
Un message flash est défini lors d'une requête et affiché une seule fois à la suivante, typiquement « Enregistré. » après une redirection. Rangez-le dans la session, puis lisez-le et supprimez-le en une étape :
Définir un cookie avec setcookie
setcookie() prend le nom, la valeur et un tableau d'options (PHP 7.3 et suivants). Définissez ces quatre options sur chaque cookie, sauf si vous avez une raison de ne pas le faire :
<?php
setcookie('theme', 'dark', [
'expires' => time() + 60 * 60 * 24 * 30, // 30 days; 0 means "until the browser closes"
'path' => '/', // send it on every page, not just this folder
'secure' => true, // only over HTTPS
'httponly' => true, // JavaScript cannot read it
'samesite' => 'Lax', // not sent on most cross-site requests
]);
$theme = $_COOKIE['theme'] ?? 'light';
Deux choses piègent souvent :
$_COOKIEne change pas dans la même requête. Il contient ce que le navigateur a envoyé avec cette requête. Un cookie que vous définissez maintenant apparaît dans$_COOKIEà la suivante.- Les cookies sont des en-têtes, donc
setcookie()doit s'exécuter avant toute sortie, exactement commesession_start()etheader().
Pour supprimer un cookie, redéfinissez-le avec le même nom et le même path et une expiration passée : setcookie('theme', '', ['expires' => time() - 3600, 'path' => '/']).
Stocker un tableau dans un cookie
Une valeur de cookie est une chaîne d'environ 4 Ko au maximum, stockez donc les données structurées en JSON, et traitez ce qui revient comme non fiable : le visiteur peut le modifier. N'utilisez jamais unserialize() sur un cookie : elle peut créer des objets de vos propres classes et exécuter leurs méthodes magiques, alors que json_decode() ne renvoie jamais que des tableaux, chaînes, nombres, booléens, null ou stdClass.
La page json_encode présente les options. Pour tout ce qui dépasse quelques valeurs courtes, gardez les données dans la session (ou une base de données) et ne stockez qu'une clé dans le cookie.
Jetons « se souvenir de moi »
Un cookie « se souvenir de moi » ne doit contenir ni l'identifiant de l'utilisateur ni le hash du mot de passe. Stockez un long jeton aléatoire dans le cookie et seulement son hash dans la base de données, et comparez avec hash_equals() :
Les valeurs changent à chaque exécution, car random_bytes() est aléatoire. Si la base de données fuit, les hashs sont inutiles sans les cookies, et hash_equals() compare en temps constant pour que la vérification ne révèle aucune information de durée.
Session ou cookie : lequel utiliser
Session ($_SESSION) | Cookie ($_COOKIE) | |
|---|---|---|
| Stockage | Sur le serveur | Dans le navigateur |
| Le visiteur peut le lire ou le modifier | Non (seulement l'identifiant) | Oui |
| Taille | Limitée par votre stockage | Environ 4 Ko par cookie |
| Durée | Jusqu'à la fermeture du navigateur ou l'expiration de la session | Jusqu'à sa date expires |
| À utiliser pour | Utilisateur connecté, panier, jeton CSRF, messages flash | Thème, langue, choix de consentement, jeton « se souvenir de moi » |
Erreur fréquente : headers already sent
session_start(), setcookie() et header() envoient toutes des en-têtes HTTP, et les en-têtes ne peuvent être envoyés qu'avant le corps. Toute sortie préalable, même une ligne vide avant <?php dans un fichier inclus, produit :
Warning: session_start(): Session cannot be started after headers have already been sent in /var/www/page.php on line 3
Warning: Cannot modify header information - headers already sent by (output started at /var/www/page.php:2) in /var/www/page.php on line 4
Le second message vous dit où la sortie a commencé (page.php:2) : allez à cette ligne et supprimez la sortie, ou placez session_start() au-dessus. Dans les fichiers qui ne contiennent que du PHP, omettre le ?> final évite que des espaces parasites après lui deviennent de la sortie.
Questions fréquentes
Quelle est la différence entre une session et un cookie en PHP ?
Un cookie est stocké dans le navigateur du visiteur et envoyé avec chaque requête, donc le visiteur peut le lire et le modifier. Une session stocke ses données sur le serveur ; le navigateur ne garde qu'un identifiant de session aléatoire dans un cookie (PHPSESSID). Placez tout ce qui doit être fiable, comme l'identifiant de l'utilisateur connecté, dans $_SESSION.
Comment détruire une session à la déconnexion en PHP ?
Videz les données, supprimez le cookie de session et détruisez la session stockée : $_SESSION = [];, puis setcookie(session_name(), '', time() - 3600, '/'), puis session_destroy();. Redirigez ensuite pour que la page suivante reparte de zéro.
Comment supprimer un cookie en PHP ?
Redéfinissez-le avec le même nom, le même chemin et le même domaine, et une date d'expiration passée : setcookie('theme', '', ['expires' => time() - 3600, 'path' => '/']);. Faites aussi unset($_COOKIE['theme']) si la suite du script courant le lit, car $_COOKIE ne change qu'à la requête suivante.
Combien de temps dure une session PHP ?
Par défaut, le cookie de session dure jusqu'à la fermeture du navigateur (session.cookie_lifetime = 0) et le serveur peut supprimer les données de session après 1440 secondes (24 minutes) d'inactivité (session.gc_maxlifetime). Pour une expiration fixe, stockez l'heure de la dernière requête dans la session et vérifiez-la vous-même.
Pourquoi session_start() affiche-t-elle headers already sent ?
L'identifiant de session voyage dans un en-tête de cookie, et les en-têtes doivent être envoyés avant toute sortie. Un echo, du HTML, ou même une ligne vide ou un BOM avant <?php envoie la sortie en premier. Appelez session_start() tout en haut du script, avant tout affichage.