Skip to main content

什麼是 Lottery 類別

Illuminate\Support\Lottery 是可將機率式操作以流暢 API 表達的工具類別。可以簡潔地寫出如「每 100 個請求執行 1 次處理」、「僅對部分請求記錄詳細日誌」等模式。
實作位於 src/Illuminate/Support/Lottery.php。Laravel 亦於 Session GC、Cache Lock 的 prune 等框架內部活用此類別。

基本用法

以整數比例指定機率

Lottery::odds($chances, $outOf) 指定「outOf次中outOf 次中 chances 次中選」的機率。

以小數指定機率

省略 $outOf 並傳入 0.01.0 的小數,則會直接作為機率使用。
小數指定時,值若超過 1.0 會拋出 RuntimeException

不帶 callback 回傳布林值

若未設定 winner / loser,choose() 中選時回傳 true,未中時回傳 false

執行多次

若對 choose($times) 傳入次數,會回傳結果的陣列。

作為 Callable 傳入

Lottery 實例實作了 __invoke,可直接傳入接受 callable 的 API。

實務使用情境

1. Cache 的 prune(每 100 次僅執行 1 次)

適合刪除過期記錄等無需每次執行的維護處理。

2. 遙測、取樣(僅部分請求記錄詳細日誌)

若將所有請求都記錄成本過高,可用於取樣。

3. 類似 A/B 測試的行為

以機率將使用者分派至 2 條程式碼路徑。

4. 作為 Scheduler 的輔助,隨機執行定期任務

當希望在多台伺服器上避免重複執行且隨機執行某任務時可用。

Laravel 框架內的機率模式

Laravel 也於框架內部廣泛使用機率式維護處理。部分實作因為在 Lottery 類別新增之前撰寫,直接使用 random_int(),但思維相同。
1

Session:垃圾回收

Illuminate\Session\Middleware\StartSession::configHitsLottery() 使用 config/session.phplottery 設定,以 random_int 進行機率判定並執行 GC。
2

DatabaseLock:過期 Lock 的 prune

Illuminate\Cache\DatabaseLock::acquire() 於每次取得 Lock 時以相同比例模式刪除過期 Lock。
3

DB::whenQueryingForLongerThan — 傳入 Lottery 類別的範例

Lottery 實例可作為 callable 傳入,可直接用於慢查詢偵測的 callback。
Session 與 DatabaseLock 直接使用 random_int(),而使用 Lottery 類別的優點是可透過 alwaysWin() / alwaysLose() / fix() 於測試中控制結果。套件開發選擇 Lottery 類別可提升可測試性。

測試時的使用

具備隨機性的程式碼測試中,可使用 Lottery 提供的測試 API。

Lottery::alwaysWin() — 恆使中選

Lottery::alwaysLose() — 恆使未中

Lottery::fix() — 以序列固定結果

可以 true/false 的陣列控制多次呼叫的結果。
alwaysWin() / alwaysLose() / fix() 會變更全域靜態屬性。請務必於測試的 tearDown() 呼叫 Lottery::determineResultNormally()

Lottery::setResultFactory() — 注入自訂 factory

若需更精細的控制,可使用自訂 factory。

套件開發的活用

於服務提供者註冊

若於套件的服務提供者中組入維護處理,可透過 Lottery 分散負載。

從設定值讀取 odds

若允許使用者從設定檔變更機率,會更方便調整。

於 Middleware 進行取樣

API 參考

相關頁面

Macroable trait

學習為既有類別新增方法的擴充模式。

Conditionable trait

學習透過 when() / unless() 設計條件分支鏈。
最後修改於 2026年8月2日