Laravel Eloquent 存储库 - 查询给出意外结果?
Laravel Eloquent Repository - Query giving unexpected result?
我正在使用 laravel eloquent 查询来获取属于一个部门的所有学生的结果。
关系是这样的:
每个部门都有 classes。
每个 class 有学生。
如果我们在 MySQL 上写这篇文章,我们可以有两个版本:
假设我们想要属于第 5 系的学生。
1.
select * from class
inner join student on class.id = student.class_id
where class.department_id = 5;
等价LaravelEloquent查询:
return $classRepo->where(['department_id'=>5])
->select(['id','department_id'])
->with(['students'])
->get();
2.
select * from student
inner join class on class.id = student.class_id
where class.department_id = 5;
等价LaravelEloquent查询:
return $studentRepo
->with(['class' => function($query){
$query->select(['id', 'department_id'])
->where(['department_id' => 5]);
}])
->get();
没想到第一个版本的结果是这样的:
[
{
"id": 3,
"department_id" : 5,
"students": [
{
"id": 61060,
"name" : "Mark"
},
{
"id": 61061,
"name" : "Tony"
}
]
}
]
从第二个版本开始是这样的:
[
{
"id": 61057,
"name" : "Smith",
"class": null
},
{
"id": 61058,
"name" : "Jason",
"class": null
},
{
"id": 61060,
"name" : "Mark",
"class": {
"id": 3,
"department_id": 5
}
},
{
"id": 61061,
"name" : "Tony",
"class": {
"id": 3,
"department_id": 5
}
}
]
谁能解释一下这两个版本的结果有何不同?
为什么我在第二个版本中针对 class 键有空值?
laravel eloquent 如何实际处理查询?
classRepo 是 'Classes' 的一个对象 class
class Classes extends Model{
public function students()
{
return $this->hasMany('App\repoModels\Student','class_id','id');
}
}
studentRepo 是 'Student' class
的对象
class Student extends Model{
public function class()
{
return $this->hasOne('App\repoModels\Classes', 'id', 'class_id');
}
}
这看起来是左联接,而不是内联接。
如果您从学生开始,eloquent 将显示所有学生及其对应的 class,即使它为空。
如果您以 class 开头,eloquent 将显示所有 class 及其对应的学生(忽略没有 class 的学生)。
如果您希望两个查询 return 得到相同的结果,您可能需要专门询问 eloquent 来执行内部联接。
您的查询没有正确约束。
您的eloquent查询
return $studentRepo
->with(['class' => function($query){
$query->select(['id', 'department_id'])
->where(['department_id' => 5]);
}])
->get();
说的是"Return all students with their corresponding class, BUT only give me the class if the class is in department 5".
你想让它说的是"Return all students with their corresponding class, BUT only give me students IF they are in a class in department 5"。
这里的解决方法是:
return $studentRepo
->with(['class' => function($query){
$query->select(['id', 'department_id'])
->where(['department_id' => 5]);
}])->whereHas('class', function($query) {
$query->where('department_id', 5);
})->get();
请参阅:"Querying Relationship Existence"
下的https://laravel.com/docs/5.8/eloquent-relationships
我正在使用 laravel eloquent 查询来获取属于一个部门的所有学生的结果。 关系是这样的: 每个部门都有 classes。 每个 class 有学生。
如果我们在 MySQL 上写这篇文章,我们可以有两个版本: 假设我们想要属于第 5 系的学生。
1.
select * from class
inner join student on class.id = student.class_id
where class.department_id = 5;
等价LaravelEloquent查询:
return $classRepo->where(['department_id'=>5])
->select(['id','department_id'])
->with(['students'])
->get();
2.
select * from student
inner join class on class.id = student.class_id
where class.department_id = 5;
等价LaravelEloquent查询:
return $studentRepo
->with(['class' => function($query){
$query->select(['id', 'department_id'])
->where(['department_id' => 5]);
}])
->get();
没想到第一个版本的结果是这样的:
[
{
"id": 3,
"department_id" : 5,
"students": [
{
"id": 61060,
"name" : "Mark"
},
{
"id": 61061,
"name" : "Tony"
}
]
}
]
从第二个版本开始是这样的:
[
{
"id": 61057,
"name" : "Smith",
"class": null
},
{
"id": 61058,
"name" : "Jason",
"class": null
},
{
"id": 61060,
"name" : "Mark",
"class": {
"id": 3,
"department_id": 5
}
},
{
"id": 61061,
"name" : "Tony",
"class": {
"id": 3,
"department_id": 5
}
}
]
谁能解释一下这两个版本的结果有何不同? 为什么我在第二个版本中针对 class 键有空值? laravel eloquent 如何实际处理查询?
classRepo 是 'Classes' 的一个对象 class
class Classes extends Model{
public function students()
{
return $this->hasMany('App\repoModels\Student','class_id','id');
}
}
studentRepo 是 'Student' class
的对象class Student extends Model{
public function class()
{
return $this->hasOne('App\repoModels\Classes', 'id', 'class_id');
}
}
这看起来是左联接,而不是内联接。
如果您从学生开始,eloquent 将显示所有学生及其对应的 class,即使它为空。
如果您以 class 开头,eloquent 将显示所有 class 及其对应的学生(忽略没有 class 的学生)。
如果您希望两个查询 return 得到相同的结果,您可能需要专门询问 eloquent 来执行内部联接。
您的查询没有正确约束。
您的eloquent查询
return $studentRepo
->with(['class' => function($query){
$query->select(['id', 'department_id'])
->where(['department_id' => 5]);
}])
->get();
说的是"Return all students with their corresponding class, BUT only give me the class if the class is in department 5".
你想让它说的是"Return all students with their corresponding class, BUT only give me students IF they are in a class in department 5"。
这里的解决方法是:
return $studentRepo
->with(['class' => function($query){
$query->select(['id', 'department_id'])
->where(['department_id' => 5]);
}])->whereHas('class', function($query) {
$query->where('department_id', 5);
})->get();
请参阅:"Querying Relationship Existence"
下的https://laravel.com/docs/5.8/eloquent-relationships