Skip to main content

什麼是 Laravel Pennant

Laravel Pennant 是簡潔輕量的功能旗標(Feature Flag)套件。功能旗標可用來階段性推出新功能、進行 A/B 測試,或補充 trunk-based 開發。

什麼是功能旗標

透過功能旗標,可以將程式碼的部署與發佈分離。程式碼可先部署到正式環境,再以設定控制功能的開/關。

安裝

1

安裝套件

使用 Composer 安裝 Pennant。
2

公開設定檔與 migration

使用 vendor:publish Artisan 指令公開檔案。
這會在 config/pennant.php 產生設定,並在 database/migrations 產生 migration 檔案。
3

執行 migration

建立 Pennant 用來儲存 feature flag 值的 features 資料表。

設定

可在 config/pennant.php 設定所使用的儲存 driver。Pennant 支援兩種 driver。

Feature 的定義

基於 closure 的定義

Feature 以 Feature facade 的 define 方法定義。通常在服務提供者的 boot 方法中定義。closure 會收到「scope」(通常是已認證的使用者)。
此 feature 的邏輯如下:
  • 內部團隊成員一律 ON
  • 高流量客戶為 OFF
  • 其他人以 1% 機率 ON
feature 首次被檢查時,closure 的結果會存到儲存 driver。之後就會使用已儲存的值。
若定義只回傳 Lottery,可以省略 closure。

基於類別的定義

Pennant 也支援類別式 feature 定義。使用類別方式時不需要在服務提供者中註冊。
產生的類別會放在 app/Features 目錄。只要實作 resolve 方法即可。

自訂儲存名稱

預設會儲存完整類別名稱。可用 Name 屬性自訂名稱。

攔截 feature 檢查(before 方法)

類別式 feature 可定義 before 方法。這個方法會在從儲存取得值之前於記憶體中執行;若回傳非 null 的值,就會使用該值。
before 方法適合在發生 bug 時緊急停用功能,或安排在指定日期時間才進行 rollout 的情境。

Feature 的檢查

Feature::active() / Feature::inactive()

可用 active 方法確認 feature 是否啟用。預設會對目前已認證的使用者進行檢查。
若是類別式 feature,傳入類別名稱:
也提供其他便利方法:

條件式執行(when / unless

使用 when 方法可在 feature 啟用時執行 closure。
unlesswhen 的相反,會在 feature 停用時執行第一個 closure。

HasFeatures trait

User model 加入 HasFeatures trait,即可直接從 model 檢查 feature。

Blade 指示詞

在 Blade 樣板中可使用 @feature 指示詞。

Middleware

使用 EnsureFeaturesAreActive middleware,可指定路由的存取需要哪些 feature。當 feature 停用時,會回傳 400 Bad Request
要自訂回應,可使用 whenInactive 方法。

記憶體快取

Pennant 會在單一請求內將 feature 的結果快取到記憶體。即使多次檢查同一個 feature flag,也不會產生額外的 DB 查詢。 若需要手動清除快取,可使用 flushCache 方法。

Scope

指定 scope

預設以已認證的使用者作為 scope,可用 for 方法指定任意 scope。
依團隊管理 feature 的範例:

自訂預設 scope

可透過 Feature::resolveScopeUsing 自訂預設 scope。
設定後省略 for 時就會採用預設 scope。

可為 null 的 Scope

若 scope 為 null(例如未認證路由、Artisan 指令等),當 feature 定義未支援 null,會自動回傳 false。要處理 null 時,請以 nullable 型別定義。

Rich Feature 值

feature 也可回傳 boolean 以外的值。例如在 A/B 測試中控制按鈕顏色。
使用 value 方法取得值。
在 Blade 中也能根據值進行條件分支。
使用 rich 值時,除 false 以外的所有值都會被視為啟用。
when 方法接收 rich 值時,第一個 closure 會收到該值。

取得多個 feature

使用 values 方法可一次取得多個 feature 的值。
使用 all 方法可取得所有已定義 feature 的值。
若要將類別式 feature 也納入 all 的結果,在服務提供者呼叫 discover
這會註冊 app/Features 目錄下所有的 feature 類別。

Eager Loading

在迴圈中檢查 feature 時可能會發生效能問題。可用 load 方法預先取得值來解決。
若只想取得尚未取得的值,可用 loadMissing

更新值

手動更新

可用 activate / deactivate 方法切換 feature 的開/關。
若要忘掉已儲存的值,可用 forget 方法。下次檢查時會由定義重新評估。

批次更新

可用 activateForEveryone / deactivateForEveryone 對儲存中的所有 scope 進行批次套用。

Feature 的清除(purge)

若 feature 已從應用移除或定義有變更,可將值從儲存中清除(purge)。
也可使用 Artisan 指令清除。與部署流程結合會很方便。

測試

重新定義 feature

在測試中可用 Feature::define 重新定義 feature,控制其回傳值。
tab=Pest
tab=PHPUnit
類別式 feature 也可以同樣處理。
tab=Pest
tab=PHPUnit

測試用 store 設定

可在 phpunit.xml 的環境變數指定測試中使用的 store。

自訂 Driver

若既有 driver 不符合需求,可以建立自訂 driver。實作 Laravel\Pennant\Contracts\Driver 介面即可。
在服務提供者的 boot 方法中呼叫 extend 進行註冊。
註冊後即可在 config/pennant.php 指定 driver。

總結

後續步驟

除錯與錯誤處理

了解應用程式的例外處理與回報機制。

Laravel Pulse

導入應用程式效能監控儀表板。
最後修改於 2026年8月2日