Passer au contenu principal
Pour étendre les connexions de base de données depuis un package, séparez l’enregistrement de la méthode de création de la sélection de la connexion utilisée. Le simple fait d’installer le package ne doit remplacer ni la connexion par défaut de l’application, ni toutes les connexions MySQL. Cette page a été vérifiée sur l’implémentation officielle de Laravel Framework v13.40.0. Pour les bases de la configuration des connexions, consultez Configuration de la base de données, et pour le chargement des providers, consultez Découverte automatique des packages.

Choisir le point d’extension

Le processus de création de la base de données propose des points d’extension de portées différentes. La valeur de retour du callback passé à DB::extend() n’est ni un PDO ni un Query Builder, mais une Illuminate\Database\Connection. DatabaseManager::configure() exige cette classe.
Le extend() de la base de données ne suit pas la même convention d’appel que le Illuminate\Support\Manager commun. Le premier argument du callback n’est pas le conteneur de l’application, mais le tableau de configuration de la connexion. Ne réutilisez pas tels quels les exemples d’extension d’autres drivers.

L’extension par nom de connexion prime sur le nom de driver

DatabaseManager::makeConnection() récupère la configuration, puis choisit la méthode de création dans l’ordre suivant.
  • DB::extend('reporting', ...) s’applique à database.connections.reporting.
  • DB::extend('mysql', ...) s’applique aux connexions dont le driver est mysql et qui n’ont pas d’extension côté nom de connexion.
  • Les deux utilisent le même registre d’extensions. En tenant compte des collisions entre noms de connexion et noms de driver, utilisez des noms propres au package.
  • extend() ne crée pas de tableau de configuration. Si vous enregistrez seulement l’extension sans configuration de connexion portant ce nom, une exception est levée.

Sélectionner explicitement un nom de driver propre

Voici un exemple minimal qui relie le nom propre acme-sqlite à la création standard d’une connexion SQLite. Ce n’est pas un exemple d’implémentation d’un nouveau protocole de base de données ou d’un dialecte SQL. Il montre la frontière entre enregistrement et sélection lors de la distribution d’un adaptateur propre. On suppose une structure où Acme\DatabaseBridge\ correspond à src/ via le PSR-4 de Composer, et le fichier est placé dans src/DatabaseBridgeServiceProvider.php.
db.factory est le binding de la ConnectionFactory partagée par Laravel. Comme la Factory standard est appelée directement, on ne revient pas à la sélection d’extension du DatabaseManager, et on peut réutiliser la création différée du PDO SQLite ainsi que la création de la Connection. Ce callback est exécuté lors de la première résolution de la connexion. Le boot() du provider se contente d’enregistrer la méthode de création, sans tester la connexion ni exécuter de migrations. Chargez-le comme un provider normal non différé, avant que la connexion cible ne soit résolue pour la première fois. L’application utilisatrice ajoute la connexion au tableau connections existant de config/database.php. Le default n’est pas modifié.
Préparez le fichier SQLite à l’avance et vérifiez les droits d’écriture avant de l’utiliser. Ne concevez pas le package pour qu’il crée le fichier dès son chargement.
L’utilisateur transmet le nom de connexion acme_reports, et non le nom de driver acme-sqlite. Dans l’exemple, le driver est converti en sqlite avant d’être transmis à la Factory, donc getDriverName() retourne aussi sqlite après la création.
Rappeler DB::connection($name) depuis le resolver relance la création de la même connexion, qui n’est pas encore conservée. Pour éviter la récursion, créez la Connection avec la Factory ou votre propre adaptateur.

Le remplacement par une sous-classe de Connection a une autre portée

Pour remplacer la classe Connection elle-même d’un driver existant, il existe Connection::resolverFor(). Le callback peut recevoir une Closure qui crée le PDO de manière différée, plutôt qu’un PDO déjà connecté. Cependant, cet enregistrement est conservé dans une propriété statique de la classe Connection. Si vous l’enregistrez pour sqlite, il affecte toutes les connexions SQLite nouvellement créées par la Factory standard, y compris l’exemple acme-sqlite ci-dessus. Il ne peut pas servir à remplacer une seule connexion nommée.
  • Le callback doit retourner une sous-classe de Connection propre à la base cible. La Connection de base seule ne conserve pas la Grammar, le Processor, etc. propres à la base de données.
  • La Factory sépare createConnector() et createConnection(). Enregistrer resolverFor() ne fournit pas pour autant un connecteur PDO pour un driver inconnu.
  • Si le resolver propre de DB::extend() n’utilise pas la Factory standard, la vérification de resolverFor() dans la Factory n’est pas non plus effectuée.
  • Un nouvel enregistrement pour le même driver écrase le précédent. Vérifiez les conflits avec d’autres packages et la persistance entre tests au sein d’un même processus PHP.
Un package qui souhaite limiter son impact devrait d’abord envisager DB::extend() avec un nom de connexion ou de driver propre.

Distinguer reconnect et purge

Le DatabaseManager conserve les Connection créées par nom de connexion. Modifier la configuration ou le resolver n’est pas répercuté automatiquement sur les connexions déjà créées. En particulier, reconnect() n’est pas une API qui remplace entièrement la classe ou le tableau de configuration de la Connection conservée. Pour appliquer un changement de classe d’extension ou de configuration de connexion, appelez purge() à un moment sûr, sans transaction en cours, puis récupérez une nouvelle connexion.
purge() ne remplace pas les références à la Connection détenues par d’autres services ou variables. De plus, les noms de connexion ::read, ::write et ::direct sont des clés de conservation distinctes : ne supposez pas qu’un purge du nom de base les supprime toutes en une fois.Ne réécrivez pas à la légère la configuration d’une connexion partagée en cours d’exécution, par exemple pour changer de tenant. Avec des workers de longue durée, vérifiez non seulement la mise à jour du cache de configuration, mais aussi le redémarrage du processus et l’impact sur les services conservés.

Tester l’enregistrement et la création du package

Avec Orchestra Testbench, chargez le provider et sélectionnez réellement le driver propre. Voici un exemple de tests/DatabaseBridgeTest.php. L’environnement d’exécution nécessite PDO et le driver SQLite.
Comme le contenu de :memory: est perdu à la déconnexion, ce test ne s’attend pas à ce que les tables ou les données soient conservées. Dans un vrai package, ajoutez également :
  • Le resolver du nom de connexion est prioritaire sur celui du nom de driver.
  • Un nouvel enregistrement sous le même nom et forgetExtension() ne remplacent pas les Connection déjà créées.
  • Les exceptions en cas de configuration obligatoire manquante, et le comportement en cas d’échec de connexion.
  • Les fonctionnalités que vous vous engagez à fournir sur les bases prises en charge : migrations, transactions, séparation read/write, etc.
  • L’enregistrement et l’état des connexions ne se mélangent pas avec des workers de longue durée ou en combinaison avec plusieurs packages.

Points à vérifier lors de la maintenance

  • L’activation se fait-elle via un nom propre, sans écraser silencieusement la connexion par défaut ou les drivers intégrés ?
  • Évitez-vous de placer des Closure ou des objets de connexion dans le cache de configuration, en gardant le processus de création dans le provider ?
  • Les destinations de connexion et les identifiants sont-ils gérés comme une configuration d’application de confiance ?
  • Avez-vous revérifié les arguments de extend(), l’ordre de création de la Factory et les éléments transférés par reconnect() sur les versions de Laravel prises en charge ?
  • Indiquez-vous aux utilisateurs la procédure de recréation après un changement de configuration et le redémarrage des workers ?

Pages associées

Sources primaires consultées

Dernière modification le 3 novembre 2026