Laravel 中Collection过滤已获取数据集计数返回0的问题求助
问题原因
- 第一个过滤逻辑的错误:你SQL查询中
whereIn('status',[1,4,6,7])作用的是关联模型bursaries.statuses的status字段,并非学生表本身的status字段。你在Collection层直接调用$students->where('status', '7')是尝试读取学生模型上的status属性,该属性不存在/无对应值,所以过滤结果为空。 - 第二个过滤逻辑的错误:你直接读取
$student->qualification,但qualification字段大概率不属于学生表,而是存在于你预加载的bursaries、enrolments、courses等关联模型中,读取不存在的属性返回null,自然匹配不到对应条件,计数为0。 - 额外注意:Laravel Collection的
where方法默认是严格类型匹配,如果目标status字段是数字类型,传字符串'7'也会导致匹配失败。
解决方法
1. 按关联属性过滤(无需修改原有查询)
如果需要保留原有查询逻辑,直接通过预加载的关联属性做过滤:
统计状态为7的学生数
$summary['students_transfer'] = $students->filter(function ($student) { // 判断学生关联的助学金状态中是否存在值为7的记录 return $student->bursaries->pluck('statuses')->flatten()->contains('status', 7); })->count();
统计研究生类学生数
假设qualification字段在bursaries表中,对应写法如下,若字段属于其他关联模型,修改层级即可:
$summary['students_postgraduate'] = $students->filter(function ($student) { return $student->bursaries->contains(function ($bursary) { return in_array($bursary->qualification, ['Postgraduate', 'Postgraduate in Training']); }); })->count();
2. 优化方案(查询时附加字段,提高过滤性能)
如果要降低Collection遍历关联的性能开销,可以在查询时就把需要的统计字段附加到学生模型上:
// 原有查询逻辑基础上修改 $students = $bursary_administrator->students() ->whereHas('bursaries.statuses', function($query) use ($request) { // 原有whereHas逻辑不变 $query->whereIn('status',[1,4,6,7]) ->whereYear('status_start','<=',$request->year) ->where(function ($query) use ($request){ $query->whereYear('status_end','>=',$request->year) ->orWhereNull('status_end'); }) ->where(function ($query) use ($request){ $query->whereYear('registration_date','<=',$request->year) ->orWhereNull('registration_date'); }); }) // 附加需要的统计字段到学生模型,模型名请对应你项目的实际命名 ->addSelect([ 'latest_bursary_status' => BursaryStatus::select('status') ->whereColumn('bursary_id', 'bursaries.id') ->latest('status_start') ->take(1), 'qualification' => Bursary::select('qualification') ->whereColumn('student_id', 'students.id') ->take(1) ]) ->with('bursaries','bursaries.statuses','bursaries.enrolments','bursaries.enrolments.courses') ->orderBy('student_name') ->orderBy('student_middle_names') ->orderBy('student_surname') ->get();
修改后就可以直接用简单的过滤写法:
$summary['students_transfer'] = $students->where('latest_bursary_status', 7)->count(); $summary['students_postgraduate'] = $students->whereIn('qualification', ['Postgraduate', 'Postgraduate in Training'])->count();
内容的提问来源于stack exchange,提问作者SupaMonkey
相关产品推荐
相关产品推荐

