ServiceProvider,整理如何將設定視為套件的公開 API 來維護。本頁以Laravel 套件開發為前提,並使用 laravel/framework 的 v13.34.0 確認實作。
公開與合併是不同的處理
publishes() 會註冊複製來源與複製目的地。在 vendor:publish 複製檔案之前,使用者的 config 目錄不會改變。另一方面,mergeConfigFrom() 會更新啟動時的設定儲存庫,而不會改寫檔案本身。
register() 的合併使用預設值。
mergeConfigFrom() 只合併最上層
ServiceProvider::mergeConfigFrom() 會先傳入套件的設定,再傳入應用程式既有的設定,並執行 array_merge()。若字串鍵相同,應用程式端的值會優先。
以下範例僅使用陣列重現框架的合併處理。
enabled 會被補上,但 transport 會整個陣列被取代,transport.retries 不會保留。重點在於:若使用者已公開舊的 transport 陣列,即使你在同一個陣列中新增鍵,也不會被補上。
以 replaceConfigRecursivelyFrom() 補上巢狀設定
Laravel 13 的ServiceProvider 中,還有 protected 方法 replaceConfigRecursivelyFrom()。此方法以相同的順序執行 array_replace_recursive()。
若你希望設定 API 能個別覆寫巢狀的字串鍵,請如下修改提供者的 register()。對於同一個設定鍵,不需要與前述的 mergeConfigFrom() 併用。
$defaults 與 $overrides,結果如下。
replaceConfigRecursivelyFrom() 是本頁所確認的 Laravel 13 原始碼中存在的方法。請將其與官方套件開發文件所介紹的 mergeConfigFrom() 區分,並確認對應版本的框架實作後再使用。數值鍵的清單不會被整體取代
遞迴取代並不是「將陣列全部替換為使用者的值」的處理。即使是數值鍵,也只會取代相同鍵的值,使用者未指定的鍵則會保留。['slack'],database 仍會保留。此外,即使傳入 ['channels' => []],預設的清單也不會變成空的。對於通知目的地或中介層等「指定整個清單」具有意義的設定,請特別注意。
若有這類設定,請從設定結構著手檢討,例如將清單與可部分覆寫的關聯陣列分到不同的最上層鍵,並使用淺層合併。若在已公開的套件中變更合併方式,即使是相同的設定檔,行為也會改變,因此請不要將其視為單純的實作替換。
設定快取中保存的是合併後的值
當應用程式實作了CachesConfiguration,且 configurationIsCached() 為 true 時,兩個方法都會略過合併處理。在一般的 Laravel 應用程式中,存在設定快取的啟動即屬於此情況。
ConfigCacheCommand 會刪除舊的設定快取,啟動新的應用程式並取得整個設定儲存庫。在該次啟動中,提供者的設定會被合併,結果則保存到快取檔案。之後的啟動中,LoadConfiguration 會讀取這些值。
因此,即使更新套件後預設值或合併方式有所改變,持續使用舊快取的應用程式也不會反映這些變更。在使用設定快取的部署中,請以更新後的程式碼重新建立快取。
php artisan config:clear。請不要自行決定快取的產生位置,交由 Laravel 的指令管理即可。
發布設定變更前的確認
在套件的測試中,除了未公開的設定之外,也要將舊版本殘留的設定作為輸入。- 即使未公開設定,也能取得必要的預設值。
- 使用舊的已公開設定時,使用者的值會優先,且新的項目會依設計被補上。
- 對於巢狀陣列、數值鍵的清單與空陣列,覆寫的約定不會改變。
- 在使用端應用程式中
config:cache能成功執行,且在使用快取的另一次啟動中也會得到相同的設定。
相關頁面
套件的測試
註冊服務提供者,驗證設定與服務的運作。
版本相容性管理
將公開 API 的變更與發布方針及持續維護連結起來。