Zum Hauptinhalt springen
Wenn ein Paket Datenbankverbindungen erweitern soll, trennen Sie die Registrierung der Erzeugungslogik von der Auswahl der genutzten Verbindung. Die bloße Installation sollte weder die Standardverbindung der Anwendung noch sämtliche MySQL-Verbindungen ersetzen. Diese Seite basiert auf dem offiziellen Quellcode von Laravel Framework 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.
extend() der Datenbank folgt nicht derselben Aufrufkonvention wie das gemeinsame Illuminate\Support\Manager. Das erste Argument des Callbacks ist nicht der Anwendungscontainer, sondern das Konfigurations-Array der Verbindung. Übernehmen Sie Beispiele für andere Treibererweiterungen nicht unverändert.

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ür database.connections.reporting.
  • DB::extend('mysql', ...) gilt für Verbindungen mit dem driver mysql, 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 Namen acme-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.
Legen Sie die SQLite-Datei vorab an und prüfen Sie die Schreibrechte, bevor Sie sie nutzen. Gestalten Sie das Paket nicht so, dass allein das Laden eine Datei erzeugt.
Nutzer übergeben den Verbindungsnamen 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.
Wenn Sie innerhalb des Resolvers erneut DB::connection($name) aufrufen, landen Sie wieder bei der Erzeugung derselben, noch nicht vorgehaltenen Verbindung. Erzeugen Sie die Connection mit der Factory oder einem eigenen Adapter, um Rekursion zu vermeiden.

Der Austausch durch eine Connection-Unterklasse hat eine andere Reichweite

Um die Connection-Klasse eines bestehenden Treibers selbst zu ersetzen, gibt es Connection::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() und createConnection(). Eine Registrierung mit resolverFor() 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 von resolverFor() 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.
Pakete, die ihre Auswirkungen begrenzen möchten, sollten zunächst 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.
purge() ersetzt keine Connection-Referenzen, die andere Services oder Variablen halten, durch die neue Verbindung. Außerdem verwenden die Verbindungsnamen mit ::read, ::write und ::direct eigene Schlüssel. Gehen Sie nicht davon aus, dass ein purge des Basisnamens diese ebenfalls gesammelt entfernt.Schreiben Sie geteilte Verbindungskonfigurationen nicht leichtfertig zur Laufzeit um, etwa um zwischen Mandanten zu wechseln. Prüfen Sie bei langlebigen Workern nicht nur die Aktualisierung des Konfigurations-Caches, sondern auch den Neustart des Prozesses und die Auswirkungen auf vorgehaltene Services.

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ür tests/DatabaseBridgeTest.php. Die Ausführungsumgebung benötigt PDO und den SQLite-Treiber.
Da der Inhalt von :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 von reconnect() ü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

Herangezogene Primärquellen

Zuletzt geändert am 3. November 2026