Laravel 5.3 使用 with() 方法预先加载关系
Posted
技术标签:
【中文标题】Laravel 5.3 使用 with() 方法预先加载关系【英文标题】:Laravel 5.3 eager loaded relations using method with() 【发布时间】:2017-04-23 18:34:07 【问题描述】:我对使用 with() 方法的 Laravel 5.3 急切加载的关系有疑问。
要么我做错了,要么我理解错了。
我运行这段代码:
$result = Post::with(['cmets' => function ($query) $query->where('content', 'like', '"%blanditiisx%"'); ])->get();通过根据经验检查数据库表“cmets”,我知道只有一条评论在其“内容”列中包含“blanditiisx”一词。
因此,由于给定的评论只能属于一篇帖子,而我们只有一条符合“where”条件的评论,所以我希望只获得一篇帖子。
令我惊讶的是,上面的代码返回了我在数据库中的所有帖子。
如果有人能告诉我哪里出了问题,我将不胜感激。
这是我的工作:
发布
我有 Post 类,其中定义了这种关系:
/** * 一对多关系 * * @return \Illuminate\Database\Eloquent\Relations\hasMany */ 公共函数 cmets() 返回 $this->hasMany(Comment::class);它适用于这个帖子表:
+------------+------------------+------+-----+---- -----+----------------+ |领域 |类型 |空 |钥匙 |默认 |额外 | +------------+------------------+------+-----+---- -----+----------------+ |编号 | int(10) 无符号 |否 |优先级 |空 |自动增量 | | created_at |时间戳 |是 | |空 | | |更新时间 |时间戳 |是 | |空 | | |标题 | varchar(255) |否 | |空 | | |蛞蝓 | varchar(255) |否 |统一 |空 | | |总结 |正文 |否 | |空 | | |内容 |正文 |否 | |空 | | |见过|小整数(1) |否 | | 0 | | |活跃 |小整数(1) |否 | | 0 | | |用户 ID | int(10) 无符号 |否 |穆尔 |空 | | +------------+------------------+------+-----+---- -----+----------------+评论
我有 Comment 类,其中定义了这种关系:
/** * 一对多关系 * * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ 公共功能 post() 返回 $this->belongsTo(Post::class);它适用于这个 cmets 表:
+------------+------------------+------+-----+---- -----+----------------+ |领域 |类型 |空 |钥匙 |默认 |额外 | +------------+------------------+------+-----+---- -----+----------------+ |编号 | int(10) 无符号 |否 |优先级 |空 |自动增量 | | created_at |时间戳 |是 | |空 | | |更新时间 |时间戳 |是 | |空 | | |内容 |正文 |否 | |空 | | |见过|小整数(1) |否 | | 0 | | |用户 ID | int(10) 无符号 |否 |穆尔 |空 | | | post_id | int(10) 无符号 |否 |穆尔 |空 | | |删除_at |时间戳 |是 | |空 | | +------------+------------------+------+-----+---- -----+----------------+编辑:
实际上我的初始代码有效,它只是以一种让我感到困惑的方式返回结果。
它的作用是为每个帖子返回一个集合。
大部分都是空的。只有那些属于查询约束的集合才会填充数据。
其余部分是空的,但仍被提取,因此可以使用 count() 将它们过滤掉。
当然,他们很渴望。
【问题讨论】:
【参考方案1】:你可以试试whereHas()
:
$result = Post::whereHas('comments', function ($query)
$query->where('content', 'like', '"%blanditiisx%"');
)->with('comments')->get();
它允许向关系约束添加自定义约束,例如检查评论的内容。
或者试试:
Post::whereHas('comments', function ($query)
$query->where('content', 'like', '"%blanditiisx%"');
)
->with(['comments' => function ($query)
$query->where('content', 'like', '"%blanditiisx%"');
])
->get();
Docs
【讨论】:
我知道 has()/whereHas() 有效,但它仍然会被急切加载吗? 不,这就是我在查询中添加with('comments')
的原因。但是,如果您只想获得过滤后的评论,请在其中添加 where
约束。
你可以使用whereHas
和with
的组合得到结果。
那么,你在说什么,通过与('cmets') 链接,我会急切地加载它,对吧? ----- 至于我的(不工作示例) - 在 Laravel 文档laravel.com/docs/5.3/eloquent-relationships#one-to-many 中,如果您在该页面上找到“约束急切负载”,您会发现:“有时您可能希望急切加载关系,但也为急切加载查询指定额外的查询约束。”——因此似乎暗示应该可以精细化查询。他们甚至举了我的例子——这没有用。
感谢您的宝贵时间。我很感激。你的回答只是把我推向了正确的方向。实际上我的初始代码有效,它只是以一种让我感到困惑的方式返回结果。它的作用是为每个帖子返回一个集合。其中大部分是空的。只有那些属于查询约束的集合才会填充数据。其余部分是空的,但仍被提取,因此可以使用 count() 将它们过滤掉。当然,他们很渴望。再次感谢。【参考方案2】:
with() 方法用于预加载相关数据,而不是过滤您已有的查询。请参阅 whereHas() 方法了解您要查找的过滤。
【讨论】:
根据 Laravel 文档laravel.com/docs/5.3/eloquent-relationships#one-to-many,如果您在该页面上找到“约束急切负载”,您会发现类似的示例并说明:“有时您可能希望急切加载关系,但也指定急切加载查询的附加查询约束。“ - 因此似乎表明,应该可以精细化查询。 这限制了“急切加载查询”。在您的示例中,这意味着限制您要加载的 cmets。您似乎希望它限制将加载哪些帖子。这就是 whereHas() 的用途。以上是关于Laravel 5.3 使用 with() 方法预先加载关系的主要内容,如果未能解决你的问题,请参考以下文章