Passer au contenu principal
Pour fournir une destination de stockage de session propre depuis un package, séparez l’enregistrement du stockage de la sélection par l’application. Le simple fait d’installer le package ne doit pas changer l’endroit où l’état de connexion est stocké : concevez-le pour que l’utilisateur puisse l’activer après avoir évalué l’impact sur les sessions existantes. Cette page a été vérifiée sur les sources officielles de Laravel Framework v13.39.0. Pour les opérations de base, consultez Session, et pour le chargement automatique des providers, consultez Découverte automatique des packages.

extend reçoit un handler, pas un Store

Le callback de Session::extend() retourne un handler de stockage qui implémente le SessionHandlerInterface de PHP. Ce n’est pas une API qui retourne directement un Store implémentant Illuminate\Contracts\Session\Session ou un Repository de cache. SessionManager::callCustomCreator() transmet la valeur de retour du callback à buildSession(), qui l’enveloppe dans un Store ou un EncryptedStore selon session.encrypt. Le nom du cookie et session.serialization sont appliqués à ce moment-là. Dans le traitement HTTP normal, le middleware StartSession gère le démarrage et l’enregistrement de la session. Pour fournir un handler, le package n’a pas besoin d’appeler session_start() ni session_set_save_handler().

Distinguer les éléments du contrat de stockage

Pour implémenter un backend propre, remplissez les rôles suivants. Comme le Store se charge de la sérialisation et de la restauration, le handler ne doit pas appliquer à nouveau serialize() ou json_encode() au tableau de session. Lorsque le chiffrement est activé, stockez tel quel la chaîne traitée par EncryptedStore.
Distinguez l’absence de données d’une panne du backend. Le Store::readFromHandler() examiné traite un résultat de lecture vide ou false comme une session vide. De plus, Store::save() ne vérifie pas la valeur de retour du write() du handler.Si votre package doit toujours traiter les pannes comme des exceptions, explicitez cette politique et testez-la : ne masquez pas les exceptions du stockage, et pour les backends qui retournent false, détectez-le dans le handler et convertissez-le en exception. Laravel ne réessaie pas forcément automatiquement et ne signale pas forcément l’échec de l’enregistrement.

N’enregistrer que la création dans boot

L’exemple minimal suivant réutilise le CacheBasedSessionHandler intégré. Il n’implémente pas de nouveau protocole de stockage : il montre comment enregistrer un driver propre qui utilise un store de cache nommé. Acme\SessionBridge\ correspond à src/ via le PSR-4 de Composer. Préparez le provider dans src/SessionBridgeServiceProvider.php.
Session::extend() récupère le SessionManager et enregistre la création, mais le store de cache du callback n’est pas encore résolu à ce stade. Le stockage n’est créé que lorsque ce driver est sélectionné pour la première fois. N’exécutez ni vérification de connexion ni écriture de données dans le boot() du provider. Si vous utilisez votre propre implémentation de SessionHandlerInterface, remplacez le handler retourné par le callback. Aller jusqu’à new Store(...) ne correspond plus à la valeur de retour attendue par le SessionManager.
  • Chargez le provider comme un provider normal, non différé.
  • Terminez l’enregistrement avant la première utilisation de la session. Si un autre provider résout votre driver plus tôt, vérifiez aussi l’ordre de chargement.
  • Utilisez un nom de driver propre au package. Un extend() portant le même nom écrase la création, et l’enregistrement d’un nom de driver intégré prend le pas sur l’implémentation intégrée.

L’application utilisatrice fait un choix explicite

L’utilisateur modifie les clés correspondantes de son config/session.php existant. Les autres réglages restent en place.
Pour le stockage, ajoutez un store nommé au tableau stores existant de config/cache.php. L’exemple suivant utilise la connexion Redis default. La configuration de la connexion Redis et le client nécessaire sont préparés par l’application.
La connexion et le préfixe de cet exemple sont déterminés par la configuration du store de cache. Comme le chemin ne passe pas par le createRedisDriver() du driver de session Redis intégré, ajouter session.connection ou session.prefix ne sera pas automatiquement pris en compte par ce callback. Ce callback ne modifie ni le Repository ni la configuration du stockage : il utilise le store nommé tel quel. Le store array de test partage lui aussi le même espace de stockage au sein d’une même application. Le package ne doit pas réécrire inconditionnellement session.driver, le nom du cookie ou le préfixe de cache global de l’application. Vérifiez aussi avec l’utilisateur que l’espace de stockage n’est pas partagé avec d’autres usages et que plusieurs serveurs peuvent utiliser le même stockage.
Si votre seul objectif est un stockage Redis ou base de données classique, commencez par les drivers de session intégrés. Un driver propre est un point d’extension pour les cas où un nouveau stockage ou des règles de stockage supplémentaires sont nécessaires.

Préserver l’unité du TTL et le format de stockage

Le constructeur de CacheBasedSessionHandler reçoit la durée de conservation en minutes. Comme write() transmet à chaque fois $minutes * 60 au put() du Repository de cache, l’exemple ci-dessus renouvelle le TTL à chaque écriture. gc() retourne 0 et délègue l’expiration au cache. En revanche, la durée que StartSession transmet au gc($lifetime) du handler est en secondes. N’implémentez pas un stockage qui utilise directement la valeur de session.lifetime comme des secondes. Par ailleurs, les changements suivants ne se limitent pas à un renommage de configuration. Si une mise à jour du package modifie ces éléments, prévoyez des instructions de réauthentification, décidez s’il faut une migration, et envisagez les déploiements où l’ancienne et la nouvelle version coexistent. Comme dans Gestion de la compatibilité de versions de package, incluez le format de stockage et les clés de configuration dans la spécification publique que vous maintenez.

Un Store déjà créé n’est pas remplacé par un simple changement de configuration

Manager, la classe parente du SessionManager, conserve les drivers créés par nom. De plus, SessionServiceProvider enregistre session.store comme singleton. forgetDrivers() n’est pas non plus une API de suppression des données de session. Recréer le Store pendant une requête en cours provoque des incohérences avec les données déjà lues ou avec d’autres références. Le CacheManager de cet exemple conserve lui aussi les stores nommés. Si vous modifiez leur configuration de connexion, re-résoudre seulement le SessionManager ne suffit pas. Dans les déploiements qui utilisent le cache de configuration, reconstruisez le cache, et redémarrez les workers longue durée pour qu’ils chargent le nouveau code et la nouvelle configuration. Le redémarrage de l’application et la migration des données stockées sont deux tâches distinctes.

Le stockage de session et le verrouillage des requêtes sont distincts

Implémenter un handler personnalisé ne suffit pas à sérialiser les requêtes parallèles sur une même session. Le blocage de StartSession utilise les verrous du store de cache choisi avec session.block_store, qui n’est pas forcément le même que le stockage de la session elle-même. Si vous contrôlez cela avec Route::post(...)->block() ou similaire, vérifiez séparément un store de cache prenant en charge les verrous, le partage entre plusieurs serveurs, ainsi que les durées d’attente et de détention. Le package ne doit pas activer de lui-même le blocage pour toute l’application.

Tester jusqu’à l’enregistrement et la relecture

Pour un package qui utilise Orchestra Testbench, chargez le provider et préparez des tests qui sélectionnent réellement votre driver. Voici un exemple de tests/SessionDriverTest.php. Le cache array de test n’utilise aucune connexion externe.
Ce test est un test isolé qui recrée le Store au sein d’une même application. Il ne vérifie ni le middleware HTTP, ni l’aller-retour des cookies, ni la persistance vers un autre processus, ni l’expiration ou les verrous d’un vrai Redis. N’utilisez pas array comme stockage partagé en production. Avant de publier un handler propre, ajoutez aussi les points suivants.
  • Un ID non stocké ou expiré retourne une chaîne vide
  • La chaîne stockée est restaurée sans modification et ne peut plus être récupérée après suppression
  • L’unité et le renouvellement du TTL, et l’expiration sur le vrai backend
  • Les échecs de lecture, d’écriture et de suppression produisent les valeurs de retour ou exceptions définies
  • L’aller-retour avec session.encrypt activé et les formats de sérialisation pris en charge
  • Le simple chargement du provider n’accède pas au stockage et ne détourne pas la sélection des drivers intégrés
  • Si nécessaire, des tests HTTP passant par le vrai middleware web et les cookies, ainsi que le verrouillage des requêtes parallèles

Pages connexes

Session

Lecture et écriture de session, données flash et régénération de l’ID.

Implémentation interne de Manager

Création et conservation des drivers personnalisés, et délégation au driver par défaut.

Stores de cache personnalisés pour les packages

Répartition des rôles entre le Store de cache servant de stockage et le Repository, et contrat du TTL.

Cycle de vie des services d'un package

Dépendances conservées par les workers longue durée et isolation de l’état.

Sources primaires

Dernière modification le 2 novembre 2026