Laravel 4.1 Ожидающая загрузка вложенных отношений с ограничениями

Я пытаюсь заставить Eager-Loading вложенные отношения с ограничениями работать. Кажется, что каждый дает тот же пример вложенных отношений с нетерпением:

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

Вместо этого я хочу, чтобы все пользователи были связаны с сообщением определенного идентификатора. Но в то же время я также хочу получить комментарии, связанные с этим сообщением.

В 4.1 я достиг последнего, я мог бы сделать:

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

Есть ли способ жениться на этих двух и ограничить вложенные отношения?

Ответ 1

На самом деле это было намного проще, чем мысли.

Учитывая эти модели:

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", автоматически возвращается, и мы можем получить его, выполнив следующее, не используя лишний "с", как это было предложено в предыдущем ответе:

var_dump($user->posts);

Ответ 2

Если отношения в моделях верны, вы можете просто сделать:

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

Вы можете добавить столько отношений, сколько хотите (или до предела памяти;)).

Он также работает со сводными таблицами.

Ответ 3

Это трудно сделать в контексте User- > Post- > Comment, но вы можете легко сделать это, начиная с Post, если это вам подходит:

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

поскольку он загрузит всех пользователей и все комментарии, связанные с данным сообщением.

- edit: Не доверяйте первому предложению, это так просто:

// $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 запроса, чтобы сделать это