Laravel+PostgreSQL学生成绩专业筛选逻辑扩展实现咨询
问题描述
场景说明
学生成绩示例
| 科目 | 等级 |
|---|---|
| (1011) 英语 | A |
| (1449) 数学 | D |
| (2100) 历史 | B |
| (1211) 生物 | A |
| (1112) 计算科学 | C |
等级对照表
| 分值 | 等级 |
|---|---|
| 1 | A |
| 2 | B |
| 3 | C |
| 4 | D |
| 5 | E |
专业准入要求
| 专业 | 最低要求 |
|---|---|
| (CS101) 计算机科学 | 数学 - C、计算科学 - C |
| (NS102) 护理 | 生物 - C |
| (AC101) 会计 | 数学 - D |
| (TS103) TESL | 英语 - B |
要求:不符合资格的专业不显示在下拉菜单中(示例中仅护理、会计、TESL需展示)。
现有代码局限
目前Laravel代码仅能筛选数学科目,通过统计成绩不符合要求的记录数来排除CS101,现有代码如下:
$count_result = Result::where('app_id', $request->app_id)->where('subject_code', '1449')->where('grade_code', '>', '3')->count(); //check result math C, if not, exlude CS101 if ($count_result > 0) { $data = OfferedProgram::select("offered_program.id as id", "offered_program.sts as sts", "branches.name as branch_name", "courses.name as course_name") ->join("branch_course", "branch_course.id", "=", "offered_program.branch_course_id") ->join("branches", "branches.id", "=", "branch_course.branch_id") ->join("courses", "courses.id", "=", "branch_course.course_id") ->where("session_id", request()->session_id) ->where("offered_program.sts", true) ->where('offered_program.total_quota', '>', 0) ->whereIn("courses.level", [1,2]) ->whereNotIn('courses.code', ['CS101']) ->get(); } else { // display all programs $data = OfferedProgram::select("offered_program.id as id", "offered_program.sts as sts", "branches.name as branch_name", "courses.name as course_name") ->join("branch_course", "branch_course.id", "=", "offered_program.branch_course_id") ->join("branches", "branches.id", "=", "branch_course.branch_id") ->join("courses", "courses.id", "=", "branch_course.course_id") ->where("session_id", request()->session_id) ->where("offered_program.sts", true) ->where('offered_program.total_quota', '>', 0) ->whereIn("courses.level", [1,2]) ->get(); }
需要扩展代码实现所有专业的动态筛选逻辑。
解决方案
要实现全专业的动态筛选,核心是把专业准入要求结构化处理,通过学生成绩逐一校验每个专业的要求,最后筛选出符合条件的专业。
步骤1:结构化存储专业要求
方案A(推荐):数据库存储
新增两张表(或扩展现有表)来结构化存储要求:
subjects表:存储科目基础信息,字段包括id、code(如1011)、name(英语)course_requirements表:存储专业准入规则,字段包括course_code(如CS101)、subject_code(如1449)、min_grade_code(如3,对应等级C)
这种方式方便后续修改要求,无需改动代码。
方案B(快速临时方案):代码配置数组
如果暂时不想改数据库,可在代码中定义配置数组模拟:
$courseRequirements = [ 'CS101' => [ '1449' => 3, // 数学最低C(grade_code <= 3) '1112' => 3 // 计算科学最低C ], 'NS102' => [ '1211' => 3 // 生物最低C ], 'AC101' => [ '1449' => 4 // 数学最低D(grade_code <= 4) ], 'TS103' => [ '1011' => 2 // 英语最低B(grade_code <= 2) ] ];
步骤2:获取学生成绩映射
把当前学生的所有成绩转换成科目代码 => grade_code的关联数组,方便快速查询:
$studentGrades = Result::where('app_id', $request->app_id) ->pluck('grade_code', 'subject_code') ->toArray();
步骤3:校验每个专业的准入资格
遍历所有目标专业,判断学生是否满足该专业的所有要求:
$eligibleCourseCodes = []; // 获取所有需要筛选的专业代码(从数据库或配置中取) $allCourses = Course::whereIn('level', [1,2])->pluck('code')->toArray(); foreach ($allCourses as $courseCode) { $requirements = $courseRequirements[$courseCode] ?? []; $isEligible = true; foreach ($requirements as $subjectCode => $minGradeCode) { // 学生未考该科目,或成绩低于要求(grade_code数值更大),则不满足 if (!isset($studentGrades[$subjectCode]) || $studentGrades[$subjectCode] > $minGradeCode) { $isEligible = false; break; } } if ($isEligible) { $eligibleCourseCodes[] = $courseCode; } }
步骤4:整合到查询中
直接用whereIn筛选符合条件的专业,替代原来的硬编码排除逻辑:
$data = OfferedProgram::select( "offered_program.id as id", "offered_program.sts as sts", "branches.name as branch_name", "courses.name as course_name" ) ->join("branch_course", "branch_course.id", "=", "offered_program.branch_course_id") ->join("branches", "branches.id", "=", "branch_course.branch_id") ->join("courses", "courses.id", "=", "branch_course.course_id") ->where("session_id", request()->session_id) ->where("offered_program.sts", true) ->where('offered_program.total_quota', '>', 0) ->whereIn("courses.level", [1,2]) ->whereIn("courses.code", $eligibleCourseCodes) // 仅保留符合条件的专业 ->get();
额外优化建议
- 优先采用数据库存储专业要求,后续维护更灵活
- 给
Result和Course模型添加关联关系,简化成绩和要求的查询 - 可缓存学生的合格专业列表,避免重复计算校验逻辑
内容的提问来源于stack exchange,提问作者Hanis Harun
相关产品推荐
相关产品推荐

