Laravel电子课程按测验成绩逐级解锁注册功能异常排查
核心问题
你的代码逻辑存在4个致命错误,完全无法匹配预设的解锁规则:
- 前后课程查询逻辑完全写反:将ID小于当前课程的最大值赋值给
$next变量,ID大于当前课程的最大值赋值给$previous,变量语义和实际取值完全颠倒,后续判断从根源上失效 - 完全缺失测验分数校验环节:业务规则要求前置课程测验得分≥75%才可解锁下一门,你的代码全程没有读取用户测验成绩的逻辑
- 状态值被循环反复覆盖:嵌套foreach遍历全量课程、全量课时的过程中,每次匹配都会重置
$enrolled和$enable_enroll的值,最终保留的只是最后一次循环的结果,和用户实际学习进度没有关联 - 存在严重的性能问题:Blade模板循环中每次都执行全量课程、全量课时查询,属于典型的N+1查询问题,课程数量稍多就会导致页面加载缓慢
- 附带一个HTML语法错误:Enroll Now按钮位置多写了一个
</h3>闭合标签,会导致页面结构错乱
修复步骤
不要在Blade模板中编写业务逻辑和数据库查询,所有状态计算提前在控制器层处理完成后,再将结果传给视图渲染。
1. 控制器层处理课程状态
假设你的测验成绩表关联用户ID、课程ID、分数字段(满分100分),在对应控制器方法中加入如下逻辑:
public function courseList() { $user = backpack_user(); // 预加载课时数据,按ID升序取所有课程 $courses = Course::with('lessons')->orderBy('id', 'asc')->get(); $firstCourseId = $courses->min('id'); $passedCourses = collect(); $enrolledCourses = collect(); if ($user) { // 取用户所有测验得分≥75分的课程ID,即已完成通过的课程 $passedCourses = \App\Models\QuizResult::where('user_id', $user->id) ->where('score', '>=', 75) ->pluck('course_id'); // 取用户已报名的课程ID $enrolledCourses = $user->enrollement()->pluck('course_id'); } // 为每个课程计算解锁/报名状态 $courses->map(function ($course) use ($firstCourseId, $passedCourses, $enrolledCourses) { $course->is_enrolled = false; $course->can_enroll = false; // 第一门课程默认开放 if ($course->id === $firstCourseId) { $course->can_enroll = !$enrolledCourses->contains($course->id); $course->is_enrolled = $enrolledCourses->contains($course->id); return $course; } // 取当前课程紧邻的前置课程ID $prevCourseId = Course::where('id', '<', $course->id)->max('id'); // 前置课程测验通过则当前课程可报名 if ($passedCourses->contains($prevCourseId)) { $course->can_enroll = !$enrolledCourses->contains($course->id); } // 已报名的课程标记为已加入状态,取消可报名标记 if ($enrolledCourses->contains($course->id)) { $course->is_enrolled = true; $course->can_enroll = false; } return $course; }); return view('你的课程列表视图路径', compact('courses')); }
注意:如果你的测验得分是用小数存储(例如0.75代表75分),请将分数判断条件改为
->where('score', '>=', 0.75);如果你的测验成绩模型名、表字段和示例不一致,替换成实际的名称即可。
2. 简化Blade模板代码
删除模板中原有@php块内的所有计算逻辑,直接使用控制器传入的状态变量渲染:
@foreach($courses as $course) <div class="col max-mb-30" data-aos="fade-up"> <div class="course"> <div class="thumbnail"> <a href="{{url('course/'.$course->id)}}" class="image"> <img src="{{asset($course->thumbnail)}}" alt="Course Image"> </a> </div> <div class="info"> <span class="price">{{$course->course_name}}</span><br> {{$course->short_description}} @if(count($course->lessons) > 1) <h3 class="title"><a href="{{url('lessons-grid/'.$course->id)}}">View Details</a></h3> @else <h3 class="title"><a href="{{url('course/'.$course->id)}}">View Details</a></h3> @endif @if($course->can_enroll) @if(count($course->lessons) > 1) <h3 class="title"><a href="{{url('course/'.$course->id)}}">Enroll Now</a></h3> @endif @elseif($course->is_enrolled) Enrolled @else <span class="text-muted small">* 完成前置课程测验且得分≥75%即可解锁</span> @endif <ul class="meta"> <li> <i class="far fa-file-alt"></i>{{count($course->lessons)}} @if(count($course->lessons) > 1) Lessons @else Lesson @endif </li> <li><i class="fa fa-clock-o"></i>{{$course->course_length}} min</li> </ul> </div> </div> </div> @endforeach
相关数据库表参考

内容的提问来源于stack exchange,提问作者Dipesh Adhikari
相关产品推荐
相关产品推荐

