微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

php – Laravel Eloquent渴望加载:孩子们缺少父参考(排序N 1)

我目前正在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足够“智能”并做这个简单的技巧?

更新1:我确实尝试从关系名称删除下划线 – 相同的结果.

更新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>";
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐