我目前正在Laravel 5.1.19上运行,并且正在观察以下问题:
假设以下模型(学生和教师为例):
class Teacher extends \Illuminate\Database\Eloquent\Model {
public function rel_students() {
return $this->hasMany(Student::class);
}
}
class Student extends \Illuminate\Database\Eloquent\Model {
public function rel_teacher() {
return $this->belongsTo(Teacher::class);
}
}
如果您随后查询教师实例并且(懒惰)急切加载其学生,则所有学生的 – > rel_teacher魔术成员会触发针对该教师的新查询:
$teacher = Teacher::with('rel_students')->find(1);
// or this, the effect is the same
$teacher = Teacher::find(1); $teacher->load('rel_students');
foreach ($teacher->rel_students as $student)
echo $student->teacher->name . "<br>";
SELECT * FROM teachers WHERE id = 1
SELECT * FROM students WHERE teacher_id IN (1)
SELECT * FROM teachers WHERE id = 1
SELECT * FROM teachers WHERE id = 1 # what is going on here?!
SELECT * FROM teachers WHERE id = 1
... and so forth for every student ...
问题:当find(1)结束时,Eloquent有一个教师#1的实例.我希望雄辩能够将对这个PHP-Objet的引用传递给渴望加载的学生,以便$student->老师返回该引用而不是触发另一个查询.
另一个消极的副作用:即使查询没有性能问题(他们是!),我会为教师#1翻译实例,这与工作单元模式非常相反.
问题:我能做些什么才能像我期望的那样表现出雄辩的表现?如果不可能:哪个PHP-ORM足够“智能”并做这个简单的技巧?
更新2:正如在答案中所提到的,使用/ load两个关系做了几乎完美的工作:$teacher-> load(‘rel_students.rel_teacher’).
这会将对教师的查询减少到2,但仍然存在$student-> rel_teacher!== $teacher的问题.这是好的,直到有人修改任何一个对象,然后它开始变得毛茸茸.
解决方法:
如果你想从学生中引用老师,你需要为每个学生延迟加载它们(‘rel_students.rel_teacher’)然后回显$student-> rel_teacher->名称或使用你正在循环的教师模型关于echo $teacher->名称
编辑
$teacher = Teacher::with('rel_students.rel_teacher')->find(1);
foreach($teacher->rel_students as $student)
{
if($teacher->id != $student->rel_teacher->id)
{
dd('error');
}
echo $student->rel_teacher->name . "<br>";
}