在我的Laravel项目中,我有一个课程模型(和一个底层表(。现在,我正试图编写一个本地作用域,用于返回特定用户已完成的所有课程。"完成"的定义是,在名为"lesson_results"的表中存在一行,该行具有本课程的ID和用户ID。
我目前的范围如下:
public function scopeFinished($query, User $user)
{
return $query->join('lesson_results', function($join) use($user)
{
$join->on('lesson_results.lesson_id', '=', 'lessons.id')
->where("user_id", $user->id);
});
}
这有点奏效。当我做一个课程::finished($user(->get((时,我会为该用户得到正确的课程。然而,返回的集合中的课程都有错误的ID!我看到的ID是lesson_results表中的ID。因此,当我从其中一个返回的项目中检查$session->id时,我不会从该课程中获得id,而是从lesson_results表中相应行中获得id。
我已经检查了mysql,从Laravel发送的完整查询是以下
select * from `lessons` inner join `lesson_results` on `lesson_results`.`lesson_id` = `lessons`.`id` and `user_id` = 53
此查询DO返回两个名为id的列(一个来自课程表,另一个来自lesson_results表(,并且Laravel似乎对返回的结果使用了错误的列。
我不知道我是走错了路,还是某个地方有漏洞?
这是Laravel 7.6.1。
编辑:好的,我想我现在真的解决了。但不太确定这是一个真正的解决方案还是一个变通办法。我添加了一个select((调用,所以返回行现在是
return $query->select('lessons.*')->join('lesson_results', function($join) use($user)
这使得它只返回课程表中的内容。但这真的需要吗?
一个相同的列名将被另一个列名覆盖。
解决方案1:
指定具有该列的表,如果其他表的列具有相同的列名,则使用别名。
Lesson::finished($user)->select('lessons.*', 'lesson_results.id AS lesson_result_id', 'lesson_results.column1', 'lesson_results.column2',...)->get();
解决方案2:
或者你可以使用Eloquent Builder急切地加载whereHas
,(假设你已经建立了模型Lesson
和模型LessonResult
之间的关系(
public function scopeFinished($query, User $user)
{
return $query->whereHas('lessonResults', function($query) use($user)
{
$query->where("user_id", $user->id);
});
}
所以你可以得到这样的教训:
Lesson::finished($user)->get();