You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.31 20:48:46