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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 16:16:11