Laravel 8 搭配 Vue3 如何获取带关联答案的测验嵌套数组
问题根源
你现在拿到扁平结构的核心原因是,通过DB门面联表查询时,单条测验对应的每一条答案都会生成独立的结果行,系统不会自动按测验维度做数据聚合,拿不到符合要求的层级嵌套结果。要实现目标的层级数组,有两种可落地的实现方案,优先推荐用Eloquent关联的方式,代码更少、维护成本更低。
方案1:用Eloquent关联实现(推荐)
Laravel的Eloquent本身就支持嵌套预加载,不需要手动写join逻辑就能自动生成符合要求的嵌套结构:
- 第一步:在对应模型中定义好关联关系
SubCourse模型(对应sub_courses表)定义和测验的一对多关系:// app/Models/SubCourse.php public function quizzes() { return $this->hasMany(Quiz::class); }Quiz模型(对应quizzes表)定义和答案的一对多关系:// app/Models/Quiz.php public function answers() { return $this->hasMany(QuizAnswer::class, 'quiz_id'); }QuizAnswer模型(对应quiz_answers表)不需要额外定义关联,作为多的一端被关联即可。
- 第二步:通过预加载嵌套关联取数
直接链式调用with加载两层关联即可,系统会自动把同个测验下的所有答案聚合到对应的测验节点下:
返回的结果结构为:每个测验条目下自动携带// 比如取指定子课程下的所有测验及嵌套答案 $subCourseId = 1; // 替换为实际要查询的子课程ID $quizzes = Quiz::with('answers') ->select('id', 'sub_course_id', 'question') // 查询时必须带上关联外键,否则关联加载失败 ->where('sub_course_id', $subCourseId) ->get();answers集合,集合内是该测验对应的所有答案(包含答案内容、是否正确的字段),完全匹配目标结构。
方案2:保留原有DB查询逻辑手动聚合
如果你不想改动现有基于DB门面的查询逻辑,可以在拿到扁平结果后手动按测验ID做分组聚合,同样能得到嵌套结构:
$subCourseId = 1; // 替换为实际查询的子课程ID $quizzes = DB::table('sub_courses') ->select('quizzes.id as quiz_id', 'quizzes.question', 'quiz_answers.id as answer_id', 'quiz_answers.answer', 'quiz_answers.correct_answer') ->join('quizzes', 'sub_courses.id', '=', 'quizzes.sub_course_id') ->join('quiz_answers', 'quizzes.id', '=', 'quiz_answers.quiz_id') ->where('sub_courses.id', $subCourseId) ->get() ->groupBy('quiz_id') // 按测验ID将同个测验的所有答案行分到一组 ->map(function ($quizGroup) { $firstRow = $quizGroup->first(); return [ 'quiz_id' => $firstRow->quiz_id, 'question' => $firstRow->question, 'answers' => $quizGroup->map(function ($answerRow) { return [ 'answer_id' => $answerRow->answer_id, 'answer' => $answerRow->answer, 'correct_answer' => (bool)$answerRow->correct_answer // 显式转布尔值,避免前端判断异常 ]; })->values() ]; }) ->values();
注意事项
- 不管用哪种查询方式,返回给Vue3的JSON结构不需要额外转换,前端可以直接用嵌套层级遍历渲染题目和选项
- 用DB查询时拿到的
correct_answer是数据库原始整型值,必须显式转成布尔类型,否则前端判断正确答案时会出现逻辑问题 - 预加载关联时,select查询的字段必须包含关联依赖的外键(比如Quiz查列表时要带
sub_course_id,QuizAnswer要带quiz_id),否则关联会加载为空
内容的提问来源于stack exchange,提问作者xMrViktorx
相关产品推荐
相关产品推荐

