Installation:
composer require lonban/lottery
Publish the config (if needed):
php artisan vendor:publish --provider="Lonban\Lottery\LotteryServiceProvider"
First Use Case:
Define a prize pool in config/lottery.php:
'prize_pools' => [
'wheel' => [
'type' => 'wheel', // or 'list', 'random'
'items' => [
['name' => 'First Prize', 'weight' => 10],
['name' => 'Second Prize', 'weight' => 5],
['name' => 'Consolation', 'weight' => 85],
],
],
],
Trigger a Draw:
use Lonban\Lottery\Facades\Lottery;
$winner = Lottery::draw('wheel');
// Returns: ['name' => 'First Prize', 'weight' => 10]
Prize Pool Management:
config/lottery.php for simple use cases.Lottery::addPool():
Lottery::addPool('dynamic_wheel', [
'type' => 'wheel',
'items' => [...],
]);
Weighted Randomness:
weight keys to skew probabilities (e.g., weight: 10 = 10x chance of weight: 1).wheel/list types.Integration with Events:
LotteryDrawn events (if extended) or log draws manually:
event(new \App\Events\PrizeDrawn($winner));
User-Specific Draws:
user_id field and filter draws later:
Lottery::draw('wheel', ['user_id' => auth()->id()]);
Lonban\Lottery\Contracts\DrawStrategy for non-standard distributions (e.g., time-based weights).prize_pools table and hydrate via Eloquent:
Lottery::addPool('db_wheel', PrizePool::find(1)->toArray());
Weight Validation:
wheel/list types require weights to sum to 100. Use Lottery::validatePool() to check:
Lottery::validatePool('wheel'); // Throws \InvalidArgumentException if invalid.
$weights = array_map(fn($item) => $item['weight'] / array_sum(array_column($items, 'weight')) * 100, $items);
Random Seed Collisions:
random type uses mt_rand(). For reproducibility, set a seed:
mt_srand(123); // Before drawing.
Missing Config:
prize_pools is empty, Lottery::draw() throws RuntimeException. Validate early:
if (empty(config('lottery.prize_pools'))) {
throw new \RuntimeException('No prize pools configured.');
}
try-catch to log failures:
try {
$winner = Lottery::draw('wheel');
} catch (\Exception $e) {
\Log::error("Lottery draw failed: {$e->getMessage()}");
}
$results = collect([]);
for ($i = 0; $i < 1000; $i++) {
$results->push(Lottery::draw('wheel')['name']);
}
// Check if results match expected weights.
Custom Draw Types:
Implement DrawStrategy for new types (e.g., time_based):
class TimeBasedStrategy implements DrawStrategy {
public function draw(array $items) {
// Custom logic (e.g., higher chance at night).
}
}
Register via service provider:
Lottery::extend('time_based', function () {
return new TimeBasedStrategy();
});
Middleware for Draws: Add user validation or rate-limiting:
Lottery::macro('drawWithMiddleware', function ($pool, $context = []) {
if (!auth()->check()) {
throw new \UnauthorizedHttpException;
}
return $this->draw($pool, $context);
});
Localization: Override prize names dynamically:
Lottery::macro('drawLocalized', function ($pool) {
$winner = $this->draw($pool);
$winner['name'] = __("lottery.{$winner['name']}");
return $winner;
});
How can I help you explore Laravel packages today?