我有3个表:
- Users - courses - user_courses(多对多关系)
- 用户[id]课程[day - time - start_date - end_date]
- User_Course [user_id - course_id]
我想验证用户不能在同一天注册两个课程,时间和时间段从start_date到end_date。这对于api,我在请求中收到course_id,我已经登录了用户id。Thx
我验证用户不能两次注册同一门课程
您可以在表单请求中使用自定义验证规则来验证。
要检查课程周期是否重叠,使用CarbonPeriod
的overlaps
方法非常直接。
因为我想不出任何验证规则,我使用验证器的after
来注册一个回调方法。
use CarbonCarbonPeriod;
use IlluminateContractsValidationValidator;
use IlluminateFoundationHttpFormRequest;
class EnrollRequest extends FormRequest
{
protected $stopOnFirstFailure = true;
public function rules(): array
{
return [
'courses' => ['required', 'array'],
'courses.*' => ['required', 'exists:courses,id'],
];
}
public function withValidator(Validator $validator): void
{
$user_courses = $this->user()->courses;
$validator->after(function (Validator $validator) use ($user_courses) {
$data = $validator->getData();
$courses = Course::whereIn('id', $data['courses'])->get();
foreach ($courses as $i => $course) {
// check user hasn't enrolled in the course already
if ($user_courses->contains($course) {
$validator->errors()->add("courses.$i", 'User is already enrolled in this course.');
}
// check if the course doesn't overlap with other courses the user has
$course_period = CarbonPeriod::create($course->start_date, $course->end_date);
foreach ($user_courses as $user_course) {
if ($couse_period->overlaps($user_course->start_date, $user_course->end_date)) {
$validator->errors()->add("courses.$i", 'Course overlaps.');
}
}
}
});
}
}
// controller
public function enroll(EnrollRequest $request)
{
$request->user()->courses()->attach($request->validated()['courses']);
}
单一课程use CarbonCarbonPeriod;
use IlluminateContractsValidationValidator;
use IlluminateFoundationHttpFormRequest;
class EnrollRequest extends FormRequest
{
protected $stopOnFirstFailure = true;
public function rules(): array
{
return [
'course_id' => ['required', 'exists:courses,id'],
];
}
public function withValidator(Validator $validator): void
{
$user_courses = $this->user()->courses;
$validator->after(function (Validator $validator) use ($user_courses) {
$data = $validator->getData();
$course = Course::find($data['course_id']);
// check user hasn't enrolled in the course already
if ($user_courses->contains($course) {
$validator->errors()->add("courses.$i", 'User is already enrolled in this course.');
}
// check if the course doesn't overlap with other courses the user has
$course_period = CarbonPeriod::create($course->start_date, $course->end_date);
foreach ($user_courses as $user_course) {
if ($couse_period->overlaps($user_course->start_date, $user_course->end_date)) {
$validator->errors()->add('course_id', 'Course overlaps.');
}
}
});
}
}
// controller
public function enroll(EnrollRequest $request)
{
$request->user()->courses()->attach($request->validated()['course_id']);
}
- 关于CarbonPeriod的文档在底部https://carbon.nesbot.com/docs
- https://laravel.com/docs/10.x/validation adding-after-hooks-to-form-requests