v13.40.0 の公式実装を確認しています。接続設定の基本はデータベース設定、プロバイダーの読み込みはパッケージの自動検出を参照してください。
拡張点を選ぶ
データベースの生成処理には、異なる範囲の拡張点があります。DB::extend() に渡すコールバックの戻り値はPDOやQuery Builderではなく、Illuminate\Database\Connection です。DatabaseManager::configure() がこのクラスを要求します。
接続名の拡張がドライバー名より優先される
DatabaseManager::makeConnection() は、設定を取得してから次の順で生成方法を選びます。
DB::extend('reporting', ...)は、database.connections.reportingに対して適用されます。DB::extend('mysql', ...)は、接続名側に拡張がない、driverがmysqlの接続へ適用されます。- どちらも同じ拡張レジストリを使います。接続名とドライバー名の衝突も考慮して、パッケージ固有の名前を使います。
extend()は設定配列を作りません。拡張だけ登録しても、指定した名前の接続設定がなければ例外になります。
独自ドライバー名を明示的に選ぶ
次は独自名acme-sqlite を、標準SQLite接続の生成へ橋渡しする最小例です。新しいDBプロトコルやSQL方言を実装する例ではありません。独自アダプターを配布する際の、登録と選択の境界を示します。
Acme\DatabaseBridge\ がComposerのPSR-4で src/ に対応する構成を想定し、src/DatabaseBridgeServiceProvider.php に配置します。
db.factory はLaravelが共有する ConnectionFactory のバインディングです。標準Factoryを直接呼ぶため、DatabaseManagerの拡張選択に戻らず、SQLiteの遅延PDO生成とConnection生成を再利用できます。
このコールバックは初回の接続解決時に実行されます。プロバイダーの boot() は生成方法の登録だけを行い、接続テストやマイグレーションを実行しません。通常の非遅延プロバイダーとして、対象接続が初めて解決される前に読み込ませます。
利用アプリケーションは、config/database.php の既存の connections 配列へ接続を追加します。既定の default は変更しません。
acme_reports であり、ドライバー名 acme-sqlite ではありません。例ではFactoryへ渡す前に driver を sqlite へ変換するため、生成後の getDriverName() も sqlite です。
Connectionサブクラスへの置き換えは別の範囲
既存ドライバーのConnectionクラス自体を置き換える場合は、Connection::resolverFor() があります。コールバックには、即座に接続済みのPDOではなく、PDOを遅延生成するClosureが渡る場合もあります。
ただし、この登録はConnectionクラスのstaticプロパティに保持されます。sqlite に登録すれば、標準Factoryで新しく作るSQLite接続全体へ影響し、上の acme-sqlite の例も対象になります。接続名1つだけの置き換えとしては扱えません。
- コールバックでは対象DB用のConnectionサブクラスを返します。基底Connectionだけでは、DB固有のGrammarやProcessorなどを保てません。
- Factoryは
createConnector()とcreateConnection()を分けています。resolverFor()の登録だけで、未知のドライバーのPDOコネクターまで提供されるわけではありません。 DB::extend()の独自resolverが標準Factoryを使わなければ、Factory内のresolverFor()の確認も通りません。- 同じドライバーへの再登録は上書きです。ほかのパッケージとの競合と、同一PHPプロセス内のテストへの持ち越しを確認します。
DB::extend() を検討します。
reconnectとpurgeを区別する
DatabaseManagerは、生成済みConnectionを接続名ごとに保持します。設定やresolverを変更しても、すでに生成された接続には自動反映されません。
特に
reconnect() は、保持済みConnectionのクラスや設定配列を丸ごと置き換えるAPIではありません。拡張クラスや接続設定の変更を反映したい場合は、処理中のトランザクションがない安全なタイミングで purge() した後、新しい接続を取得します。
パッケージの登録と生成をテストする
Orchestra Testbenchでは、プロバイダーを読み込み、独自ドライバーを実際に選択します。次はtests/DatabaseBridgeTest.php の例です。実行環境にはPDOとSQLiteドライバーが必要です。
:memory: は接続の切断で内容が失われるため、このテストはテーブルやデータの保持を期待しません。実際のパッケージでは、次も追加します。
- 接続名のresolverがドライバー名のresolverより優先されること。
- 同名の再登録と
forgetExtension()が、生成済みConnectionを置き換えないこと。 - 必須設定が欠けた場合の例外と、接続失敗時の挙動。
- 対応DBでのマイグレーション、トランザクション、read/write分離など、提供を約束する機能。
- 長寿命ワーカーや複数パッケージとの併用で、登録や接続状態が混ざらないこと。
保守時の確認項目
- 独自名でオプトインし、既定接続や組み込みドライバーを黙って上書きしていないか。
- configキャッシュにClosureや接続オブジェクトを入れず、生成処理はプロバイダーに置いているか。
- 接続先や認証情報を信頼できるアプリケーション設定として管理しているか。
extend()の引数、Factoryの生成順、reconnect()の転送対象をサポート対象のLaravelで再確認したか。- 設定変更後の再生成手順とワーカー再起動を利用者へ案内しているか。