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.
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 ledriverestmysqlet 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 propreacme-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é.
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.
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 existeConnection::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()etcreateConnection(). EnregistrerresolverFor()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 deresolverFor()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.
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.
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 detests/DatabaseBridgeTest.php. L’environnement d’exécution nécessite PDO et le driver SQLite.
: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 parreconnect()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
- Développement de packages
- Conception du cycle de vie des services de package
- Fusion et cache de la configuration des packages
- Publication et mise à jour des migrations de package
Sources primaires consultées
- Documentation officielle Laravel : bases de données et connexions multiples
- Documentation officielle Laravel : service providers des packages
- DatabaseManager : ordre de création, enregistrement des extensions, conservation et reconnexion
- ConnectionFactory : création différée du PDO et resolver de Connection
- Connection : resolverFor et getResolver
- DatabaseServiceProvider : enregistrement de db et db.factory