php - 在 laravel 中过滤关系
问题描述
我有具有 hasMany 关系的 Posts 和 Comments 模型:
public function comments()
{
return $this->hasMany(Posts::class, 'posts_id', 'id');
}
在我的控制器中,我需要获取所有已发布的帖子(is_published = 1),以及所有已发布的评论,至少有 1 条已发布的评论:
$dbRecords = Posts::all()->whereStrict('is_published', 1);
$posts = [];
foreach ($dbRecords as $post) {
if (count($post->comments()) === 0) {
continue;
}
foreach ($post->comments() as $comment) {
if ($comment->is_published === 1) {
$posts[] = $post;
continue(2); // to the next post
}
}
}
但是,这样的解决方案是丑陋的。此外,我将获得所有已发布的帖子,包括已发布和未发布的评论,因此我将被迫再次在资源中过滤评论。
我发现的另一个解决方案 - 使用原始查询:
$dbRecords = DB::select("SELECT posts.*
FROM posts
JOIN comments ON posts_id = posts.id
WHERE posts.is_published = 1
AND comments.is_published = 1
HAVING count(posts.id) > 0;");
$users = array_map(function($row) { return (new Posts)->forceFill($row); }, $dbRecords);
但它并没有解决需要过滤资源中未发布评论的问题。
解决方案
- 在 Laravel eloquent 中使用 Eager loading 来消除
n+1
查询问题。with
- 用于查询关系存在
has
或whereHas
功能。
在你的情况下,它会是这样的:
// Retrieve all posts that have at least one comment
$posts = Post::has('comments')->with('comments')->get();
// Retrieve posts with at least one comment and which are published
$callback = function($query) {
$query->where('is_published ', '=', '1');
}
$posts = Post::whereHas('comments', $callback)
->with(['comments' => $callback])
->where('is_published ', '=', '1')
->get();
推荐阅读
- flutter - Flutter全新安装flutter运行卡住
- java - 将数字总和递归减少到一位数字
- c++ - 我可以在运行时检查内置类型吗?
- node.js - 在 Angular 的 rxjs 订阅方法中捕获错误消息文本
- google-maps - 有没有办法知道一条道路有多少条车道?
- python - KeyError:使用 conda install 安装底图时出现“PROJ_LIB”
- python - 检查集合中的所有点是否在同一条线上
- java - 在 try catch 块内执行 if-else 循环的问题
- google-maps-api-3 - 来自地理编码 API 的响应
- javascript - 更改默认 Laravel Mix Minimizer/Minifier (webpack)