Laravel Pennant 介紹
前天(2023/8/18)完成了 Laravel Pennant 的工作坊,今天來分享一下這個套件的介紹。
Laravel Pennant 能做什麼事?
Laravel Pennant 主要功能是管理 Feature 與 Scope 組合後的狀態表。例如下面的表格:
Feature | Scope | Active |
---|---|---|
awesome_feature | miles | ON |
awesome_feature | john | OFF |
awesome_feature | null | OFF |
another_feature | miles | OFF |
team_feature | miles_team | ON |
Scope 的定義是抽象的,沒有明確規定要如何對應,它代表的是一個被標示的實體(identified entity)。實務上的範例如,可以對應到人,或者是團隊等。像上表的 miles 就能夠使用 awesome_feature 功能,而 john 則不行。
Scope 也可以是 null,不指定通常就代表著全域功能切換。
控制 Feature 狀態
Laravel Pennant 提供四個公開方法讓開發者可以控制狀態:
- 單一 scope 更新
Feature::for($object)->activate($feature); |
- 批量 scope 更新
// $objects 為 array |
- 現有 DB 所保存的 scope 狀態更新
Feature::activateForEveryone($feature); |
- 清除狀態
Feature::purge($feature); |
Laravel Pennant 原始碼分析
其實 Laravel Pennant 官網裡面說明寫得很詳細,接著來看看裡面的架構。
classDiagram class FeatureManager class PendingScopedFeatureInteraction class Driver <<Interface>> Driver class ArrayDriver class DatabaseDriver class Decorator Driver <|-- ArrayDriver Driver <|-- DatabaseDriver Driver <|-- Decorator Decorator o-- Driver FeatureManager *-- Driver Decorator --> PendingScopedFeatureInteraction PendingScopedFeatureInteraction o-- Driver
管理 Feature 的主要物件是 FeatureManager
,而產生 Driver
的時候會使用 Decorator
包裝(在 resolve()
方法裡):
return new Decorator( |
Laravel 設計 Manager 的習慣,是它把當作 Aggregate Root 在做的,因此所有存取背後的 Entity 都必須要經過它。
實際在使用 FeatureManager 的時候,可以透過 __call()
直接 Proxy 到預設的 Driver:
public function __call($method, $parameters) |
有需要的話再使用 store()
方法指定 driver。
最後是 PendingScopedFeatureInteraction
類別。它的用途是讓 Decorator 整合 Scope 參數的邏輯整理在這個 class,而原本的 Decorator 則是專注在跟 Driver 互動,這是一種職責分離的處理方法。(Container 也有一樣的設計)
而對廣義的程式設計來說,這是一種 Mixin 的手法:
FeatureManager mixin Decorator |
這個結果也就讓 FeatureManager 可以同時擁有 Decorator 與 PendingScopedFeatureInteraction 所提供的方法。但架構上還是如同前面提到的:Laravel 設計 Manager 的概念,就是把 Manager 當作是 Aggregate Root。