我有五个表 students
, grades
, subjects
, terms
和 scores
. 我正在thes表上执行内部联接以返回结果 . 我的架构看起来如何:
学生表:
students
--------
id *
name
class_id (fk)
科目表:
subjects
--------
id *
name
class 表:
classes
--------
id *
name
术语表:
terms
--------
id *
name
分数表:
scores
---------------
id *
student_id (fk)
subject_id (fk)
class_id (fk)
term_id (fk)
score
我的laravel查询:
$scores = \DB::table('scores')
->join('students', 'students.id', '=', 'scores.student_id')
->join('subjects', 'subjects.id', '=', 'scores.subject_id')
->join('grades', 'grades.id', '=', 'scores.grade_id')
->join('terms', 'terms.id', '=', 'scores.term_id')
->select('students.first_name', 'students.surname', 'subjects.name as subject', 'grades.name as grade', 'terms.name as term', 'score')
->where('students.id', 1)
->whereBetween('scores.term_id', [1, 3])
->get();
当我死掉并转储它时,查询返回结果:
毫无疑问,查询返回正确的结果,但 problem 是我希望结果出现在我的html表中,如下所示:
这是它基于我现在在我的控制器和视图中的代码显示的方式 .
控制器:
public function index()
{
//
$scores = \DB::table('scores')
->join('students', 'students.id', '=', 'scores.student_id')
->join('subjects', 'subjects.id', '=', 'scores.subject_id')
->join('grades', 'grades.id', '=', 'scores.grade_id')
->join('terms', 'terms.id', '=', 'scores.term_id')
->select('students.first_name', 'students.surname', 'subjects.name as subject', 'grades.name as grade', 'terms.name as term', 'score')
->where('students.id', 1)
->whereBetween('scores.term_id', [1, 3])
->get();
// finding details of the student based on id pased
$student = Student::findOrFail(1);
// getting the name of the student
$name = $student->first_name.' '.$student->surname;
// getting the class or grade of the student (grade 12 or grade 11)
$grade = $student->grade->name;
// getting the current date
$date = Score::date();
return view('scores.home', compact('scores', 'name', 'date', 'grade'));
视图:
<table class="table table-bordered table-condensed table-striped">
<thead>
<tr>
<th scope="row">Name</th>
<td colspan="4">{{$name}}</td>
</tr>
<tr>
<th scope="row">Class</th>
<td colspan="2">{{$grade}}</td>
<th scope="row">Date</th>
<td>{{$date->toFormattedDateString()}}</td>
</tr>
<tr>
<th class="text-center">Subject</th>
@foreach($scores as $score)
<th class="text-center">{{$score->term}}</th>
@endforeach
</tr>
</thead>
<tbody>
@foreach($scores as $score)
<tr>
<td>{{$score->subject}}</td>
<td>{{$score->score}}</td>
</tr>
@endforeach
</tbody>
</table>
结果:
如上面的结果所示,术语名称 1st Period
正在重复,我该如何避免?如何在视图或控制器中重构我的查询或代码以获得我想要的结果?
3 回答
首先,我会稍微简化一下查询,只选择你还不知道的数据 . 没有必要在每一行返回学生姓名和成绩,因为他们总是一样的 .
您将获得与您的结果类似的以下集合:
现在将其转换为嵌套结构:
您将获得以下集合:
但这不是表结构 - 缺少一些术语 . 所以你需要填写缺少的条款,因为你不想在你的视图中这样做 . 我会创建一个空表结构并将数据填入其中:
使用空分数初始化表:
用给定的分数填写表格:
现在“表格”将如下所示:
将它传递给您的视图并像这样呈现表格:
您将获得以下HTML代码:
更新:
获得
$scoreTable
的更短途径可能是但它似乎不太可读 . 也可能有一个或另一个
collection
函数将替换map
函数并使事情变得更容易 . 但我不知道他们 .更新2:
这是另一种更短的方式,但在较大的数据集上可能会很慢,因为每个表格单元都会调用两次昂贵的
where()
函数 .更新3:
最后,我提出了以下解决方案,其中(我认为)是最易读/最简单快速的解决方案 .
前两行将从查询结果中提取唯一的主题和术语 . (更多关于pluck()和unique()中的unique()方法 . )然后在下面的嵌套循环中使用它们来生成具有空值的表结构(主题✕术语) . 在下一个循环中,查询结果中的分数将填入"table" .
在Laravel我们有Laravel雄辩,你只需要定义关系,你就好了 . 在你的分数模型中,假设你有一个,只需定义关系
在控制器或路线中,根据您的工作地点,只需拨打分数即可
当你用刀片呼叫学生时,你只需写
{{$score->student->name}}
然后对所有其他项目(即成绩,术语等)执行相同的操作 .
我会通过这样的方式收集与他的主题配对的分数:
然后将此新集合传递给视图,以便您可以在视图中循环
$scores_paired