跳轉到主要內容
想從套件擴充資料庫連線時,請將建立方式的註冊與所用連線的選擇分開。設計上應避免僅安裝套件就取代應用程式的預設連線或所有 MySQL 連線。 本頁確認了 Laravel Framework v13.40.0 的官方原始碼。連線設定的基本說明請參閱資料庫設定,提供者的載入請參閱套件自動探索。

選擇擴充點

資料庫的建立處理中,有適用範圍不同的擴充點。 傳給 DB::extend() 的回呼,其回傳值不是 PDO 或 Query Builder,而是 Illuminate\Database\Connection。DatabaseManager::configure() 會要求這個類別。
資料庫的 extend() 與共通的 Illuminate\Support\Manager 呼叫慣例不同。回呼的第 1 個參數不是應用程式容器,而是連線設定的陣列。請不要直接沿用其他驅動擴充的範例。

連線名稱的擴充優先於驅動名稱

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。
請事先準備好 SQLite 檔案,並確認寫入權限後再使用。不要設計成僅載入套件就會建立檔案。
使用者傳入的是連線名稱 acme_reports,而不是驅動名稱 acme-sqlite。範例中在傳給 Factory 前將 driver 轉換為 sqlite,因此建立後的 getDriverName() 也是 sqlite。
若在 resolver 內再次呼叫 DB::connection($name),就會回到尚未保留之同一連線的建立處理。為避免遞迴,請以 Factory 或自訂轉接器建立 Connection。

替換為 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(),再取得新的連線。
purge() 不會將其他服務或變數所持有的 Connection 參照替換為新的。此外,連線名稱的 ::read、::write、::direct 為不同的保留鍵,請不要以為只 purge 基底名稱就會一併刪除它們。請不要為了切換租戶等目的,輕易改寫執行中的共用連線設定。在長時間執行的 worker 中,除了更新設定快取外,也請確認處理程序的重新啟動以及對已保留服務的影響。

測試套件的註冊與建立

在 Orchestra Testbench 中載入提供者,並實際選擇自訂驅動。以下是 tests/DatabaseBridgeTest.php 的範例。執行環境需要 PDO 與 SQLite 驅動。
:memory: 會在連線中斷時遺失內容,因此此測試不預期資料表或資料會被保留。在實際的套件中,也請新增以下測試。
  • 連線名稱的 resolver 優先於驅動名稱的 resolver。
  • 同名重新註冊與 forgetExtension() 不會替換已建立的 Connection。
  • 缺少必要設定時的例外,以及連線失敗時的行為。
  • 在支援的資料庫上進行遷移、交易、讀寫分離等承諾提供的功能。
  • 在長時間執行的 worker 或與多個套件併用時,註冊與連線狀態不會混雜。

維護時的確認項目

  • 是否以自訂名稱讓使用者選擇啟用,而未默默覆寫預設連線或內建驅動。
  • 是否未將 Closure 或連線物件放入 config 快取,並將建立處理放在提供者中。
  • 是否將連線目標與認證資訊作為可信任的應用程式設定加以管理。
  • 是否已在支援的 Laravel 版本中重新確認 extend() 的參數、Factory 的建立順序以及 reconnect() 的移轉對象。
  • 是否已向使用者說明設定變更後的重新建立步驟與 worker 重新啟動。

相關頁面

參考的第一手資料

最後修改於 2026年11月3日