Laravel 8按Session获取Program Section并统计注册学生数报错求助
问题:按Session获取Program Section并统计注册学生性别数量时出错
需求概述
需要实现方法按Session获取Program Section,同时统计每个Program Section下男女学生的注册数量,但调用时触发错误。
数据库结构
terms ----- id name start_date end_date term_type active sessions -------- id term_id start_date end_date session_type students -------- id first_name last_name middle_name suffix email student_number birthdate sex lrn profile_picture programs -------- id name code description sections -------- id name code section_terms ------------- section_term_id term_id section_id program.sections -------------- id session_id academic_level_id user_id section_id max_students program_id program.subjects -------------- id subject_id program_id academic_level_id semester_level academic_levels --------------- id code name description ordering enrollment ---------- id student_id session_id program_id academic_level_id date_dropped drop_reason
相关代码
EnrollmentController代码
public function countStudentEnrollmentBySexAndProgramSection() { $programSection = ProgramSection::with('session') ->withCount(['enrollment as female_students' => function ($query) { $query->whereHas('student', function ($query) { $query->where('sex', Student::FEMALE); }); }])->withCount(['enrollment as male_students' => function ($query) { $query->whereDate('created_at', Carbon::now()); $query->whereHas('student', function ($query) { $query->where('sex', Student::MALE); }); }])->get(); return response()->json($programSection, 200); }
ProgramSection模型代码
protected $table = 'program.sections'; protected $fillable = [ 'session_id', 'academic_level_id', 'user_id', 'section_id', 'max_students', 'program_id', ]; public function session() { return $this->belongsTo('App\Models\Session', 'session_id'); } public function academicLevel() { return $this->belongsTo('App\Models\AcademicLevel', 'academic_level_id'); } public function program() { return $this->belongsTo('App\Models\Program', 'program_id'); } public function user() { return $this->belongsTo('App\Models\User', 'user_id'); } public function section() { return $this->belongsTo('App\Models\Section', 'section_id'); } public function schedules() { return $this->hasMany('App\Models\Schedule', 'section_id', 'id'); } public function classRecord() { return $this->hasOne("App\Models\Grading\ClassRecord"); } public function students() { return $this->hasManyThrough( 'App\Models\Student', 'App\Models\Student\Section', 'section_id', 'id', 'id', 'student_id', ); }
Enrollment模型代码
protected $table = 'enrollment'; protected $fillable = [ 'session_id', 'student_id', 'program_id', 'academic_level_id', 'date_dropped', 'drop_reason', ]; public function session() { return $this->belongsTo('App\Models\Session', 'session_id'); } public function student() { return $this->belongsTo('App\Models\Student', 'student_id'); } public function program() { return $this->belongsTo('App\Models\Program', 'program_id'); } public function academicLevel() { return $this->belongsTo('App\Models\AcademicLevel', 'academic_level_id'); } public function programSection() { return $this->belongsTo('App\Models\Program\Section', 'session_id', 'session_id'); } public function studentSection() { return $this->hasOne('App\Models\Student\Section'); } public function enrollmentFee() { return $this->hasMany('App\Models\Accounting\EnrollmentFee', 'enrollment_id', 'id'); } public function studentLedger() { return $this->hasMany('App\Models\Student\Ledger'); } public function lastLedger() { return $this->hasOne('App\Models\Student\Ledger')->latest(); }
Sessions模型代码
protected $table = 'sessions'; protected $fillable = [ 'term_id', 'start_date', 'end_date', 'session_type', ]; public function term() { return $this->belongsTo('App\Models\Term', 'term_id'); } public function schedules() { return $this->hasMany('App\Models\Schedule', 'session_id', 'id'); } public function enrollments() { return $this->hasMany('App\Models\Enrollment', 'session_id', 'id'); } public function sessionFees() { return $this->hasMany('App\Models\Accounting\SessionFee', 'session_id', 'id'); } public function getAllowDeleteAttribute() { return !($this->schedules()->exists() || $this->sessionFees()->exists() || $this->enrollments()->exists()); }
错误信息
message: "Call to undefined method App\Models\Program\Section::enrollment()"
解决方案
1. 错误原因
控制器中使用withCount(['enrollment' => ...])时,ProgramSection模型中未定义名为enrollment(或复数enrollments)的关联方法,Eloquent无法识别该关联。同时,enrollment表与program.sections表无直接外键,需通过session_id、program_id、academic_level_id三个字段组合关联。
2. 修正步骤
步骤1:在ProgramSection模型中添加enrollments关联
在ProgramSection模型中新增以下方法:
use App\Models\Enrollment; // ... public function enrollments() { return $this->hasMany(Enrollment::class) ->whereColumn([ 'enrollment.session_id' => 'program.sections.session_id', 'enrollment.program_id' => 'program.sections.program_id', 'enrollment.academic_level_id' => 'program.sections.academic_level_id', ]); }
步骤2:修正控制器中的withCount调用
将控制器中的enrollment改为enrollments(与关联方法名一致):
public function countStudentEnrollmentBySexAndProgramSection() { $programSection = ProgramSection::with('session') ->withCount(['enrollments as female_students' => function ($query) { $query->whereHas('student', function ($query) { $query->where('sex', Student::FEMALE); }); }])->withCount(['enrollments as male_students' => function ($query) { // 注意:原代码的whereDate('created_at', Carbon::now())仅匹配当天注册的学生,若需统计当前Session的所有注册,可移除该条件 $query->whereHas('student', function ($query) { $query->where('sex', Student::MALE); }); }])->get(); return response()->json($programSection, 200); }
步骤3:修正Enrollment模型中的programSection关联
原关联仅通过session_id匹配,逻辑不完整,需改为多字段匹配:
use App\Models\Program\Section; // ... public function programSection() { return $this->belongsTo(Section::class) ->whereColumn([ 'program.sections.session_id' => 'enrollment.session_id', 'program.sections.program_id' => 'enrollment.program_id', 'program.sections.academic_level_id' => 'enrollment.academic_level_id', ]); }
内容的提问来源于stack exchange,提问作者Kael
相关产品推荐
相关产品推荐

