Laravel8如何通过两表关联正确判断用户多课程购买状态
问题背景
现有courses(课程)、admissions(购课记录)两张数据表,业务需求为:用户已购买的课程在前端显示「已录取(Admitted)」标识,未购买的课程展示购买入口及对应价格。
原有代码存在缺陷:仅能识别单条购课记录,同一用户购买多门课程时,仅会标记1门课程为已录取状态,无法正确识别所有已购课程。
原有实现代码
控制器层原有代码
$courses = Course::orderby('id', 'desc')->get(); $admission = Admission::where('users_id', Auth::user()->id)->first() ?: app(Admission::class); return view('Backend.Student.courses', compact('courses', 'admission'));
Blade模板层原有判断代码
@if( $course->id == $admission->courses_id ) <li class="list-inline-item"> <a href="javascript:void(0)" class="btn btn-info btn-sm"><h5 class="p-0 m-0 text-white"> {{ __('Admitted') }}</h5></a> </li> @if( !empty($admission->status == 'active') ) <li class="list-inline-item"> <a href="{{ route('access.course', $course->slug) }}" class="btn btn-warning btn-sm"><h5 class="p-0 m-0 text-white"> {{ __('Continue Course') }}</h5></a> </li> @endif @else <li class="list-inline-item"> <a href="{{ route('purchase.course', $course->slug) }}" class="btn btn-info btn-sm"><h5 class="p-0 m-0 text-white"> {{ __('Admission Now') }}</h5></a> </li> <li class="list-inline-item">{{ __('Price') }}: ৳{{ number_format( $course->price , 0 , '.' , ',' ) }} BDT</li> @endif
问题根因
- 控制器层仅通过
first()方法获取当前用户的第一条购课记录,没有拉取该用户全部购课数据 - 模板层判断逻辑仅拿单条购课记录的课程ID做匹配,无法覆盖多门已购课程的匹配场景
- 原模板中
!empty($admission->status == 'active')存在逻辑错误:括号内是布尔判断结果,empty()接收布尔值时判断逻辑不符合预期,会导致状态判断失效
修复方案
第一步:调整控制器逻辑
将取单条购课记录的逻辑,改为取出当前用户所有购课记录的课程ID与对应状态,以键值对集合的形式传递给模板:
$courses = Course::orderby('id', 'desc')->get(); // 取出当前用户所有购课记录,以课程ID为键、购课状态为值生成集合,方便后续快速判断 $userAdmissions = Admission::where('users_id', Auth::user()->id) ->pluck('status', 'courses_id'); return view('Backend.Student.courses', compact('courses', 'userAdmissions'));
第二步:调整Blade模板判断逻辑
遍历课程列表时,判断当前课程ID是否存在于用户已购课程集合中即可完成状态匹配:
@if( $userAdmissions->has($course->id) ) <li class="list-inline-item"> <a href="javascript:void(0)" class="btn btn-info btn-sm"><h5 class="p-0 m-0 text-white"> {{ __('Admitted') }}</h5></a> </li> {{-- 直接从集合中读取对应课程的购课状态做判断 --}} @if( $userAdmissions->get($course->id) == 'active' ) <li class="list-inline-item"> <a href="{{ route('access.course', $course->slug) }}" class="btn btn-warning btn-sm"><h5 class="p-0 m-0 text-white"> {{ __('Continue Course') }}</h5></a> </li> @endif @else <li class="list-inline-item"> <a href="{{ route('purchase.course', $course->slug) }}" class="btn btn-info btn-sm"><h5 class="p-0 m-0 text-white"> {{ __('Admission Now') }}</h5></a> </li> <li class="list-inline-item">{{ __('Price') }}: ৳{{ number_format( $course->price , 0 , '.' , ',' ) }} BDT</li> @endif
优化说明:使用
pluck生成键值对集合的判断方式,时间复杂度为O(n),比循环嵌套判断的性能更高,即使课程和购课记录数据量较大也不会出现性能问题。
内容的提问来源于stack exchange,提问作者Happy Arif
相关产品推荐
相关产品推荐

