Laravel 4.1 Eager用约束加载嵌套关系

时间:2014-04-04 16:38:18

标签: laravel-4 eloquent eager-loading

我试图通过约束来获得Eager-Loading嵌套关系。每个人似乎都给出了热切加载嵌套关系的相同示例:

$users = User::with('posts.comments')->get();

我想要做的是获取与给定ID的帖子相关的所有用户。但与此同时,我也希望得到与该帖子相关的评论。

在4.1中,我要实现后者,我能做到:

$comments = Comment::whereHas('post', function($query) { $query->whereId(1); })->get();

有没有办法结合这两个并约束嵌套关系?

3 个答案:

答案 0 :(得分:8)

实际上发现它比思想简单得多。

鉴于这些模型:

class User extends \Eloquent {

    public function posts()
    {
        return $this->hasMany('Post');
    }

    public function comments()
    {
        return $this->hasManyThrough('Comment', 'Post');
    }       

}

class Post extends \Eloquent {

    public function user()
    {
        return $this->belongsTo('User');
    }

    public function comments()
    {
        return $this->hasMany('Comment');
    }       

}

class Comment extends \Eloquent {

    public function post()
    {
        return $this->belongsTo('Post');
    }

}

然后我们可以获取具有给定帖子的用户:

$userId = 2; $postId = 5;
$user =  User::with(['comments' => function($q) use($postId) { $q->where('post_id', $postId); }])->find($userId);

使用get()时这不起作用,因为它不会将用户限制为仅与给定帖子相关的用户。但这没关系,因为我们只对post_id $ postId的一篇文章感兴趣。由于帖子属于一个且只有一个用户,我们不必担心其他用户。因此,我们可以使用find()或first()来获得实际结果。

此外,'中间'关系即'post'会自动返回,我们可以通过执行以下操作来获取它,而无需使用前面答案中建议的额外'with':

var_dump($user->posts);

答案 1 :(得分:7)

如果模型中的关系正确,您可以这样做:

$user = User::with('posts.comments')->get();

您可以根据需要添加任意数量的关系(或内存限制;)。

它也适用于数据透视表。

答案 2 :(得分:3)

在User-> Post-> Comment的背景下很难实现这一点,但如果适合你,你可以从Post开始轻松实现这一点:

Post::with('users')->with('comments')->find(1);

因为它会加载所有用户以及与给定帖子相关的所有评论。

- 编辑:不要相信第一句话,它就像这样简单:

// $id of the post you want

User::with(['comments' => function ($q) { // this is hasManyThrough relation
  $q->where('post_id',$id);               // comments only related to given post
}])->with(['posts' => function ($q) {
  $q->whereId($id);                       // here we load only the post you want
}])->whereHas('posts', function ($q) {
  $q->whereId(1);                         // here we filter users by the post
})->get();

请注意,Laravel会运行3个查询来完成它