v13.40.0. Die Grundlagen der Verbindungskonfiguration finden Sie unter Datenbankkonfiguration, das Laden von Providern unter Paket-Discovery.
Den Erweiterungspunkt wählen
Für die Erzeugung von Datenbankverbindungen gibt es Erweiterungspunkte mit unterschiedlicher Reichweite.
Der Rückgabewert des an
DB::extend() übergebenen Callbacks ist weder ein PDO noch ein Query Builder, sondern eine Illuminate\Database\Connection. DatabaseManager::configure() setzt diese Klasse voraus.
Erweiterungen für Verbindungsnamen haben Vorrang vor Treibernamen
DatabaseManager::makeConnection() liest die Konfiguration und wählt die Erzeugungslogik in folgender Reihenfolge.
DB::extend('reporting', ...)gilt fürdatabase.connections.reporting.DB::extend('mysql', ...)gilt für Verbindungen mit demdrivermysql, für deren Verbindungsnamen keine Erweiterung existiert.- Beide nutzen dieselbe Erweiterungsregistrierung. Berücksichtigen Sie auch Kollisionen zwischen Verbindungs- und Treibernamen und verwenden Sie paketspezifische Namen.
extend()erzeugt kein Konfigurations-Array. Wenn Sie nur die Erweiterung registrieren und keine Verbindungskonfiguration unter dem angegebenen Namen existiert, wird eine Ausnahme ausgelöst.
Einen eigenen Treibernamen explizit auswählen
Das folgende Minimalbeispiel leitet den eigenen Namenacme-sqlite an die Erzeugung einer Standard-SQLite-Verbindung weiter. Es implementiert weder ein neues DB-Protokoll noch einen SQL-Dialekt. Es zeigt die Grenze zwischen Registrierung und Auswahl, wenn Sie einen eigenen Adapter ausliefern.
Angenommen wird eine Struktur, in der Acme\DatabaseBridge\ per Composer-PSR-4 auf src/ abgebildet wird; die Datei liegt unter src/DatabaseBridgeServiceProvider.php.
db.factory ist das von Laravel geteilte Binding der ConnectionFactory. Da die Standard-Factory direkt aufgerufen wird, kehrt der Ablauf nicht zur Erweiterungsauswahl des DatabaseManager zurück, und die verzögerte PDO-Erzeugung sowie die Connection-Erzeugung für SQLite lassen sich wiederverwenden.
Dieser Callback wird beim ersten Auflösen der Verbindung ausgeführt. boot() des Providers registriert nur die Erzeugungslogik und führt weder Verbindungstests noch Migrationen aus. Laden Sie ihn als gewöhnlichen, nicht verzögerten Provider, bevor die Zielverbindung zum ersten Mal aufgelöst wird.
Die nutzende Anwendung fügt die Verbindung dem bestehenden connections-Array in config/database.php hinzu. Der Standardwert default bleibt unverändert.
acme_reports, nicht den Treibernamen acme-sqlite. Da das Beispiel driver vor der Übergabe an die Factory in sqlite umwandelt, liefert auch getDriverName() nach der Erzeugung sqlite.
Der Austausch durch eine Connection-Unterklasse hat eine andere Reichweite
Um die Connection-Klasse eines bestehenden Treibers selbst zu ersetzen, gibt esConnection::resolverFor(). Dem Callback wird nicht unbedingt ein bereits verbundenes PDO übergeben, sondern unter Umständen eine Closure, die das PDO verzögert erzeugt.
Diese Registrierung wird jedoch in einer statischen Eigenschaft der Connection-Klasse gehalten. Eine Registrierung für sqlite wirkt sich auf alle neu von der Standard-Factory erzeugten SQLite-Verbindungen aus, einschließlich des obigen Beispiels acme-sqlite. Sie lässt sich nicht als Austausch für nur einen einzelnen Verbindungsnamen verwenden.
- Geben Sie im Callback eine Connection-Unterklasse für die Ziel-DB zurück. Mit der Basis-Connection allein bleiben DB-spezifische Grammar- oder Processor-Klassen nicht erhalten.
- Die Factory trennt
createConnector()undcreateConnection(). Eine Registrierung mitresolverFor()allein stellt keinen PDO-Connector für einen unbekannten Treiber bereit. - Wenn ein eigener Resolver von
DB::extend()die Standard-Factory nicht nutzt, wird auch die Prüfung vonresolverFor()innerhalb der Factory nicht durchlaufen. - Eine erneute Registrierung für denselben Treiber überschreibt die vorherige. Prüfen Sie Konflikte mit anderen Paketen und das Übertragen in andere Tests innerhalb desselben PHP-Prozesses.
DB::extend() mit eigenen Verbindungs- oder Treibernamen in Betracht ziehen.
reconnect und purge unterscheiden
Der DatabaseManager hält erzeugte Connections pro Verbindungsname vor. Änderungen an Konfiguration oder Resolver werden nicht automatisch auf bereits erzeugte Verbindungen übertragen.
Insbesondere ist
reconnect() keine API, die Klasse oder Konfigurations-Array einer vorgehaltenen Connection vollständig ersetzt. Wenn Änderungen an der Erweiterungsklasse oder der Verbindungskonfiguration wirksam werden sollen, rufen Sie zu einem sicheren Zeitpunkt ohne laufende Transaktion purge() auf und holen danach eine neue Verbindung.
Registrierung und Erzeugung des Pakets testen
Mit Orchestra Testbench laden Sie den Provider und wählen den eigenen Treiber tatsächlich aus. Es folgt ein Beispiel fürtests/DatabaseBridgeTest.php. Die Ausführungsumgebung benötigt PDO und den SQLite-Treiber.
:memory: beim Trennen der Verbindung verloren geht, erwartet dieser Test nicht, dass Tabellen oder Daten erhalten bleiben. In einem echten Paket ergänzen Sie außerdem:
- Dass der Resolver des Verbindungsnamens Vorrang vor dem Resolver des Treibernamens hat.
- Dass eine erneute Registrierung unter demselben Namen und
forgetExtension()erzeugte Connections nicht ersetzen. - Ausnahmen bei fehlender Pflichtkonfiguration und das Verhalten bei Verbindungsfehlern.
- Zugesagte Funktionen auf den unterstützten Datenbanken, etwa Migrationen, Transaktionen und read/write-Trennung.
- Dass sich Registrierungen und Verbindungszustände bei langlebigen Workern oder im Zusammenspiel mit mehreren Paketen nicht vermischen.
Prüfpunkte für die Wartung
- Wird über einen eigenen Namen per Opt-in aktiviert, ohne die Standardverbindung oder eingebaute Treiber stillschweigend zu überschreiben?
- Landen keine Closures oder Verbindungsobjekte im Konfigurations-Cache, und liegt die Erzeugungslogik im Provider?
- Werden Verbindungsziele und Zugangsdaten als vertrauenswürdige Anwendungskonfiguration verwaltet?
- Wurden die Argumente von
extend(), die Erzeugungsreihenfolge der Factory und die vonreconnect()übertragenen Elemente für die unterstützten Laravel-Versionen erneut geprüft? - Werden Nutzer über das Vorgehen zur Neuerzeugung nach Konfigurationsänderungen und den Neustart von Workern informiert?
Verwandte Seiten
- Paketentwicklung
- Lebenszyklus von Paket-Services gestalten
- Zusammenführen und Cachen von Paketkonfigurationen
- Veröffentlichen und Aktualisieren von Paket-Migrationen
Herangezogene Primärquellen
- Laravel offiziell: Datenbank und mehrere Verbindungen
- Laravel offiziell: Service Provider für Pakete
- DatabaseManager: Erzeugungsreihenfolge, Erweiterungsregistrierung, Vorhalten und Neuverbinden von Verbindungen
- ConnectionFactory: Verzögerte PDO-Erzeugung und Connection-Resolver
- Connection: resolverFor und getResolver
- DatabaseServiceProvider: Registrierung von db und db.factory