我有一个名为User
的集合,我还有一个数组,其中包含与Post
模型相关的两个模型User
。
User
集合包含主键id
,我的Post
集合中的每个模型都有一个外键user_id
。
我目前正在执行以下操作:
foreach ($users as $user) {
foreach ($posts as $post) {
if ($post->user_id == $user->id) {
$user->posts->push($post);
}
}
}
这有点奏效,但并不完全是因为它提取了所有相关帖子,而不是用户最近的两个帖子。
数组如下所示:
我的User
架构看起来像;与Post
的hasMany关系:
答案 0 :(得分:3)
您可以使用User
加载与with
相关联的帖子,例如
$user = User::with('posts')->find($id);
但您的情况听起来特别收集属于Post
的最新两个User
。要限制结果,您还可以使用范围。
Post
模型上的以下内容可行:
public function scopeLatest($query, $latest = 2)
{
return $query->limit($latest);
}
然后通过以下方式收集这些:
// The user record.
$user = User::find($id);
// Latest 2 posts for this user.
$posts = $user->posts()->latest();
// Latest 5 posts for this user.
$posts = $user->posts()->latest(5);
但是,如果您要在一个查询中加载最新的2个帖子,那么您可以建立新关系:
public function latestPosts()
{
return $this->hasMany(Post::class, 'post_id', 'id')
->orderBy('created_at', 'ASC')
->limit(2);
}
这可以通过以下方式工作:
// Load the user with the latest 2 posts.
$user = User::with('latestPosts')->find($userId);
// Access these using; this will be a Collection containing 2 `Post` records.
dd($user->latestPosts);
基本上使用Eloquent,当你调用$this->latestPosts
时,Eloquent会运行latestPosts()
并保存相关记录。使用with
这种水合作用只需一个查询即可,并且已经定义了关系。
方法latestPosts()
和属性$latestPosts
之间的区别很简单。
该方法将始终返回特定的Relation Collection,允许您链接其他条件;
所以:$user->latestPosts()->get()
与$user->latestPosts
相同。
答案 1 :(得分:1)
您不能使用查询约束/预先加载来执行此操作。这样做只有在您检索一个用户的帖子时才有效。但是,如果您尝试检索多个用户的帖子,它将失败,因为急切的加载/查询约束将限制整个相关结果。要理解,您必须查看Eloquent生成的查询。让我们来看一个你只需要一个用户帖子的例子。
$user = User::with(['posts' => function($query) {
$query->limit(2);
}])->find(1);
在这个例子中,我们得到一个主键为1的用户。我们还检索他/她的帖子,但限制它,所以我们只检索2个帖子。这是有效的,它将生成2个类似于此的查询:
select * from `users` where `users`.`id` = 1 limit 1
select * from `posts` where `posts`.`user_id` in (1) limit 2
好。现在,如果你试图获得超过1个用户(或一组用户),为什么这不起作用?例如:
$user = User::with(['posts' => function($query) {
$query->limit(2);
}])->get();
在这种情况下,我将find(1)
更改为get()
,它会生成2个这样的查询:
select * from `users`
select * from `posts` where `posts`.`user_id` in (?, ?, ?, ... ?) limit 2
重要的是看一下第二个查询。它正在检索所有相关帖子,但最后,您会看到它有limit 2
。换句话说,它将整个相关集合限制为仅2,这就是为什么查询约束不适用于此。
实现这一点实际上非常复杂,但是其他成员(Jarek Tkaczyk)提出了使用MySQL变量的解决方案,您可以在此处找到:Laravel - Limit each child item efficiently
答案 2 :(得分:0)
使用https://laravel.com/docs/5.2/eloquent-relationships#eager-loading约束可以更简单一些。
示例:用户有很多狗,但只有2个
$user = App\User::with(['dogs' => function ($query) {
$query->limit(2);
}])->find($user_id);
dump($user);
匿名约束函数在你的情况下也会有一个orderBy