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