Laravel如何实现每日事件按固定序列循环轮转分配
Laravel实现每日事件无限循环排布方案
核心逻辑
你这个规则本质是从固定起始日开始,每过1天事件编号+1,到10之后回到1无限循环,示例里的周几匹配只是刚好起始日选了周一的排布结果,不需要写任何周几判断的分支逻辑,用日期差取模的无状态方案实现最稳定,永远不会出现进度错乱问题:
- 选业务规则里第一个匹配「事件1」的周一作为固定锚点日期
- 计算目标日期和锚点日期的自然日间隔天数
- 用间隔天数对事件总数(10)取余,结果+1就是当天对应的事件编号
你可以直接套你给的规则验证:
- 锚点日(第0天,周一):0%10 +1 = 1 → 事件1
- 第6天(周日):6%10 +1 =7 → 事件7
- 第7天(下周一):7%10 +1 =8 → 事件8
- 第9天(下周三):9%10 +1 =10 → 事件10
- 第10天(下周四):10%10=0 +1=1 → 回到事件1
- 第11天(下周五):11%10=1 +1=2 → 事件2
完全匹配你列的所有规则,后续不管循环多少年,计算结果都不会错。
具体实现步骤
- 先把可变配置放全局配置文件,避免硬编码
在config/business.php(没有就新建)里添加配置项:
return [ // 业务上线后第一个匹配事件1的周一,按实际情况修改格式为Y-m-d 'event_cycle_anchor' => '2024-01-01', // 循环事件总数 'event_cycle_total' => 10, ];
- 封装通用获取方法,建议放到全局辅助函数或者业务Service层
<?php use Carbon\Carbon; use Illuminate\Support\Facades\Config; /** * 获取指定日期对应的循环事件编号 * @param string|Carbon|null $date 不传默认取当前自然日 * @return int 1-10的事件编号 */ function getCycleDailyEventId(string|Carbon $date = null): int { $targetDay = $date ? Carbon::parse($date)->startOfDay() : Carbon::today()->startOfDay(); $anchorDay = Carbon::parse(Config::get('business.event_cycle_anchor'))->startOfDay(); // 可选校验:禁止查询业务上线前的日期 if ($targetDay->lt($anchorDay)) { throw new \InvalidArgumentException('查询日期不能早于事件循环起始日'); } $daysGap = $anchorDay->diffInDays($targetDay); return ($daysGap % Config::get('business.event_cycle_total')) + 1; }
- 日常业务调用
- 获取当日对应事件:
$todayEventId = getCycleDailyEventId(); - 获取指定日期对应事件:
$testEventId = getCycleDailyEventId('2024-10-01'); - 批量生成未来N天的事件排布,直接循环日期调用即可,不需要提前把所有日期的事件存数据库,随用随算无冗余。
- 获取当日对应事件:
配套调度配置
如果需要每天零点自动触发当天事件的对应逻辑,直接在app/Console/Kernel.php里加Laravel内置任务调度就行:
protected function schedule(Schedule $schedule) { $schedule->call(function () { $currentEventId = getCycleDailyEventId(); // 此处写对应事件的业务逻辑:比如推送通知、更新活动状态、发放奖励等 })->dailyAt('00:01'); // 零点过1分执行,避免跨天临界值问题 }
扩展说明
- 后续如果要调整循环事件总数,比如改成12个事件一轮,直接改配置里的
event_cycle_total值即可,不需要修改任何业务代码 - 这个方案无状态,不需要额外存循环进度、轮次计数,不会因为服务器时间异常、手动改数据导致后续所有日期匹配错乱,稳定性远高于按周几判断、手动计数轮次的方案。
内容的提问来源于stack exchange,提问作者Unkown Kid
相关产品推荐
相关产品推荐

