Laravel如何实现用户每日仅可分享1次不重复任务的限制
Laravel实现任务分享双重限制规则方案
1. 前置表结构确认
首先确保shares表包含以下必要字段,缺失的话可以通过新增迁移补充:
user_id:关联执行分享操作的用户ID,整数类型、外键关联users表idtask_id:关联被分享的任务ID,整数类型、外键关联tasks表idcreated_at:分享操作创建时间,时间戳类型,Laravel默认自带该字段
2. 配置模型关联
分别在三个模型中配置关联关系,简化后续查询:
- 在
User模型中新增关联:
// app/Models/User.php public function shares() { return $this->hasMany(Share::class); }
- 在
Task模型中新增关联:
// app/Models/Task.php public function shares() { return $this->hasMany(Share::class); }
- 在
Share模型中新增反向关联:
// app/Models/Share.php public function user() { return $this->belongsTo(User::class); } public function task() { return $this->belongsTo(Task::class); }
3. 业务校验逻辑实现
在处理分享请求的控制器方法中加入两层校验,直接用Laravel内置的验证机制即可,不需要额外引入扩展包:
// app/Http/Controllers/TaskController.php public function share(Request $request) { $userId = auth()->id(); $todayTimeRange = [now()->startOfDay(), now()->endOfDay()]; $validated = $request->validate([ 'task_id' => [ 'required', 'integer', 'exists:tasks,id', // 校验规则1:当前用户从未分享过该任务 function ($attr, $value, $fail) use ($userId) { $shared = Share::where('user_id', $userId) ->where('task_id', $value) ->exists(); if ($shared) $fail('不可重复分享同一任务'); }, // 校验规则2:当前用户当日未执行过分享操作 function ($attr, $value, $fail) use ($userId, $todayTimeRange) { $todayShared = Share::where('user_id', $userId) ->whereBetween('created_at', $todayTimeRange) ->exists(); if ($todayShared) $fail('每日仅可进行1次任务分享'); } ] ]); // 校验通过后创建分享记录 Share::create([ 'user_id' => $userId, 'task_id' => $validated['task_id'] ]); return back()->with('success', '分享成功'); }
4. 数据库层兜底防并发
仅靠代码校验在高并发场景下可能出现穿透问题,需要给shares表新增联合唯一索引,从数据库层面阻止同一用户重复分享同一任务的记录写入:
// 生成新迁移文件执行索引添加 Schema::table('shares', function (Blueprint $table) { $table->unique(['user_id', 'task_id'], 'user_task_share_unique'); });
添加索引后可以在控制器中补充异常捕获,当并发请求触发唯一索引报错时返回友好提示即可。
可选优化
如果多处用到分享校验逻辑,可以把两个闭包校验封装成Laravel自定义验证规则类,提升代码复用性。
内容的提问来源于stack exchange,提问作者kiki
相关产品推荐
相关产品推荐

