如何解决当主键号被“跳过”或在键之间添加另一个学生时,Laravel hasmanythrough 模型将行放在错误的父级中
这是关于具有以下主键的这 4 个表。
- 课程:CursusNaam varchar
- 练习:OpdrachtID int
- 练习进度:OpdrachtVoortgangID int
- 学生:LeerlingID int
一门课程可以有很多练习(所以练习有外键 CursusNaam)。
每个学生的练习进度存储在练习进度表中(所以它有国外 键 OpdrachtID),当然练习进度与学生相关联(因此它具有外键 LeerlingID。
我试图做的是获取并显示学生完成的最新练习。我在课程模型中使用 hasManyThrough 关系做到了这一点。 当表格练习进度中只有一名学生时,这很有效。但是,当我在练习进度表中再添加一行与不同学生的数据时,它会显示从一门课程到错误课程的最后一个 OpdrachtVoortgangID!
练习进度:这对一名学生有效,显示正确:
Image of view where it shows right
INSERT INTO `opdrachtvoortgang` (`OpdrachtVoortgangID`,`LeerlingID`,`OpdrachtID`,`IsKlaar`,`Beoordeling`) VALUES
(1,1,b'1','Voldoende'),(2,2,'Onvoldoende'),(3,3,(4,4,b'0','onvoldoende'),(5,5,(6,6,'Voldoende');
练习进度错误 #1:添加另一个学生导致 OpdrachtVoortgangID:2(它所属的课程的最后一个)显示到错误的课程中:
Image of view where OpdrachtID 2 moved to wrong course
INSERT INTO `opdrachtvoortgang` (`OpdrachtVoortgangID`,-- Different student with id 2 messes it up!
(2,(7,'Voldoende');
练习进度错误 #2:我刚刚发现“跳过”一个主键数字与让另一个学生的进度介于两者之间的效果相同。
(1,
练习表:
INSERT INTO `opdrachten` (`OpdrachtID`,`Opdracht`,`CursusNaam`,`Deadline`) VALUES
(1,'1','Laravel-essentials 1','2021-02-10 13:52:26'),'2','2021-02-20 13:52:26'),'ASPAdvanced',NULL),'3','3B','2021-03-25 23:42:02');
这是课程控制器:
$cursussen = Cursus::get();
return view('home')
->with(compact('cursussen'))
这是我在视图中的显示方式:
@foreach ($cursussen as $cursus)
$cursus->getVoortgang()
@endforeach
这是课程模型:
//get the latest finished exercise by a student
function getVoortgang()
{
return $this->hasManyThrough('App\Models\OpdrachtVoortgang','App\Models\Opdrachten','CursusNaam','OpdrachtVoortGangID','OpdrachtID')
->where('LeerlingID',1) //get progress from student with ID 1
->where('IsKlaar',1) //only exercises that are finished
->whereNotNull('IsKlaar' )
->orderByDesc('OpdrachtID')
->get(); //get instead of first to show that that the progress row got displayed next to the wrong course.
}
非常感谢您的观看。 编辑:This is the output of dd($cursus->getVoortgang())
解决方法
get()
每次都返回一个对象集合。该集合中可能有 0 个或多个对象,具体取决于查询结果。
first()
在幕后调用 get()
,但它不返回结果集合,而是返回集合中的第一个条目(如果有)。
您使用哪种方法取决于您的需要。您需要所有结果的集合(使用 get()
),还是只想要集合中的第一个结果(使用 first()
)?
我想你想返回集合中的第一个结果
你一定要试试这个
function getVoortgang()
{
return $this->hasManyThrough('App\Models\OpdrachtVoortgang','App\Models\Opdrachten','CursusNaam','OpdrachtVoortGangID','OpdrachtID')
->where('LeerlingID',1) //get progress from student with ID 1
->where('IsKlaar',1) //only exercises that are finished
->whereNotNull('IsKlaar' )
->orderByDesc('OpdrachtID')
->first(); //get instead of first to show that that the progress row got displayed next to the wrong course.
}
或
function getVoortgang()
{
return $this->hasManyThrough('App\Models\OpdrachtVoortgang','OpdrachtID')
->where('LeerlingID',1) //get progress from student with ID 1
->where('IsKlaar',1) //only exercises that are finished
->whereNotNull('IsKlaar' )
->orderByDesc('OpdrachtID')
->get()
->first();
}
使用get()->first()
只会返回一条记录,如果没有找到则返回null。
并且您必须按 id 进行排序,我不知道 Cursus 的 id 列,无论它放在 orderby 类中什么
$cursussen = Cursus::orderby('id','desc')->get();
return view('home',compact('cursussen'));
,
我仍然不知道是什么导致了这种情况,但是通过使用“直通”表并向其添加连接解决了这个奇怪的问题。
function getOpdracht()
{
return $this->hasMany('App\Models\Opdrachten','CursusNaam');
}
function getOpdrachtLaatstAfgemaakt()
{
return $this->getOpdracht()
->join('opdrachtvoortgang','opdrachten.OpdrachtID','=','opdrachtvoortgang.OpdrachtID')
->where('opdrachtvoortgang.IsKlaar','1')
->where('opdrachtvoortgang.LeerlingID','1')
->orderByDesc('opdrachtvoortgangID')
->first();
}
现在它不再显示在错误的课程旁边,以防在两者之间缺少进度 ID 号或中间有另一个学生时。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。