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 連線建立的最小範例。這不是實作新資料庫協定或 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 的範例也會成為對象。無法將其視為僅替換單一連線名稱。
- 回呼中請回傳目標資料庫用的 Connection 子類別。僅使用基底 Connection,無法保留資料庫專屬的 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。 - 缺少必要設定時的例外,以及連線失敗時的行為。
- 在支援的資料庫上進行遷移、交易、讀寫分離等承諾提供的功能。
- 在長時間執行的 worker 或與多個套件併用時,註冊與連線狀態不會混雜。
維護時的確認項目
- 是否以自訂名稱讓使用者選擇啟用,而未默默覆寫預設連線或內建驅動。
- 是否未將 Closure 或連線物件放入 config 快取,並將建立處理放在提供者中。
- 是否將連線目標與認證資訊作為可信任的應用程式設定加以管理。
- 是否已在支援的 Laravel 版本中重新確認
extend()的參數、Factory 的建立順序以及reconnect()的移轉對象。 - 是否已向使用者說明設定變更後的重新建立步驟與 worker 重新啟動。