Skip to main content

Lotteryクラスとは

Illuminate\Support\Lottery は、確率ベースの操作を流れるようなAPIで表現できるユーティリティクラスです。「100リクエストに1回だけ処理を実行する」「一部のリクエストのみ詳細ログを記録する」といったパターンをシンプルに記述できます。
実装は src/Illuminate/Support/Lottery.php にあります。LaravelはこのクラスをSession GCやキャッシュロックのプルーンなど、フレームワーク内部でも活用しています。

基本的な使い方

整数比率で確率を指定する

Lottery::odds($chances, $outOf) で「outOf回中outOf 回中 chances 回当選」という確率を指定します。

小数で確率を指定する

$outOf を省略して 0.01.0 の小数を渡すと、そのまま確率として使われます。
小数指定のとき値が 1.0 を超えると RuntimeException が投げられます。

コールバックなしで真偽値を返す

winner / loser を設定しない場合、choose() は当選なら true、落選なら false を返します。

複数回実行する

choose($times) に回数を渡すと結果の配列が返されます。

Callable として渡す

Lottery インスタンスは __invoke を実装しているため、callable を受け取るAPIに直接渡せます。

実践的なユースケース

1. キャッシュのプルーン(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: 期限切れロックのプルーン

Illuminate\Cache\DatabaseLock::acquire() はロック取得のたびに同じ比率パターンで期限切れロックを削除します。
3

DB::whenQueryingForLongerThan — Lottery クラスを渡す例

Lottery インスタンスは callable として渡せるため、スロークエリ検知コールバックに直接使えます。
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() — カスタムファクトリを注入する

より細かい制御が必要な場合は、カスタムファクトリを使います。

パッケージ開発での活用

サービスプロバイダーでの登録

パッケージのサービスプロバイダーにメンテナンス処理を組み込む場合、Lottery を使って負荷を分散させます。

設定値からオッズを読み込む

確率を設定ファイルから変更可能にすると、ユーザーが調整しやすくなります。

Middleware でのサンプリング

API リファレンス

関連ページ

Macroableトレイト

既存クラスに新しいメソッドを追加する拡張パターンを学びます。

Conditionableトレイト

when() / unless() による条件分岐チェーンの設計を学びます。
最終更新日 2026年5月11日