尝试从子模型重新访问父模型的 laravel 多级关系急切加载问题

Posted

技术标签:

【中文标题】尝试从子模型重新访问父模型的 laravel 多级关系急切加载问题【英文标题】:Issue with laravel multi-level relationship eager loading trying to reaccess the parent model from the child model 【发布时间】:2020-12-22 10:06:44 【问题描述】:

我想问一下这个最好的实现是什么。

$users = User::with(['group', 'orders', 'comments'])->get()

$users->each(function($user) 
    $user->comments->each(function($comment) 
        // I know I can just add 'use' in the closure function to access the user again
        // but let's just say that the user variable is not accessible at this point of the code.
        // and the only way to access the user again is via $comment variable
        // when I access user here. it tries to fetch in the database
        $user = $comment->user;
    );
);

我的第一个解决方案是添加这行代码。

$user->comments->setRelation('user', $user);

这将解决问题,因为用户不会再从数据库中获取。 但另一个问题出现了。设置关系后,其他eagerloaded的用户关系将不包含在该级别 比如$user->group$user->orders

这是我的第二个解决方案

$users = User::with([
'group',
'orders', 
'comments', 
// trying to eager load the comments user again
'comments.user', 
'comments.user.group', 
'comments.user.orders'])->get()

这可行,但我认为这不是最好的解决方案。特别是当我有很多我渴望加载的嵌套关系时。 我只是在示例中将其限制为 3 以使其更简单。

【问题讨论】:

在这些情况下最好使用连接,因为在后台的急切加载会对关系模型产生额外的请求 感谢您的回复。但我认为这在我的情况下是不可能的。这是我正在尝试优化报告页面以提高性能的现有系统。每个雄辩的模型上已经发生了很多事情。以及我们无需过多接触代码即可快速加载所有内容的最快方式。 【参考方案1】:

我只是想出了如何解决这个问题。

$user->comments->each->setRelation('user', $user); 将从 $user 丢弃预先加载的模型。

但如果您通过each 手动设置关系。将包含所有预先加载的模型。

$user->comments->each(function($comment) use ($user) 
     $comment->setRelation('user', $user);
);

【讨论】:

以上是关于尝试从子模型重新访问父模型的 laravel 多级关系急切加载问题的主要内容,如果未能解决你的问题,请参考以下文章

Blazor 组件:从子组件更新模型时刷新父组件

绑定视图 - 如何从子列表中获取父属性的详细信息

Laravel 多级关系

使用 Laravel 模型保存多级数组

如何使用 Laravel 创建数据库驱动的多级导航菜单

Laravel/Eloquent - 创建与可能具有或不具有属性的父模型相关的多个子模型的关系