Возвращать отношения, только если пользователь вошел в систему?

У меня есть таблица Posts и Comments, где у каждого сообщения может быть несколько комментариев.

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

Вот что у меня есть до сих пор:

$posts = Post::select('posts.*')
    ->with(['comments' => function($query) {
        if (Auth::check()) {
            $query->where('user_id', Auth::user()->id);
        }
    }])
    ->get();

И мой класс модели Post.php выглядит так:

class Post extends Model
{
    public function comments()
    {
        return $this->hasMany('App\Comment');
    }
}

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

Но когда пользователь не вошел в систему, он возвращает комментарии ВСЕХ пользователей вместо того, чтобы ничего не возвращать (поскольку пользователь вошел в систему и, следовательно, у него нет комментариев).

Как я могу это исправить?


person user7863944    schedule 13.04.2017    source источник


Ответы (3)


Я могу думать об этом двумя способами.

Сначала вы можете загружать комментарии, только если пользователь вошел в систему:

$posts = Post::select('posts.*');

if(Auth::check()) {
    $posts->with(['comments' => function($query) {
        $query->where('user_id', Auth::user()->id);
    }]);
}

$posts = $posts->get();

Или вы можете загрузить все комментарии, но установить для user_id значение null, если пользователь не вошел в систему. Поскольку каждый комментарий должен иметь user_id, комментарии не возвращаются.

$posts = Post::select('posts.*')
    ->with(['comments' => function($query) {
            $query->where('user_id', Auth::check() ? Auth::id() : null);
    }])
    ->get();

Код во втором выглядит чище IMO, но первый предотвратит выполнение ненужного запроса.

person jfadich    schedule 13.04.2017

вы можете сделать небольшой трюк в своей модели поста:

class Post extends Model
{
public function comments()
{
    if(Auth::check()) {
         return $this->hasMany('App\Comment')->where('user_id', Auth::user()->id);
    }else{
         return $this->hasMany('App\Comment')->where('user_id',-1);
    }
}

}

а потом просто:

$posts = Post::select('posts.*')->with('comments')->get()

поэтому, если пользователь не вошел в систему, он вернет все комментарии с user_id "-1", что будет ничем.

person Kamal Behboudi    schedule 25.09.2018

Можно выделить, более разборчиво и практично:

$posts = Post::all();

В вашей модели Post создайте функцию, которая будет возвращать все комментарии пользователя:

public function userComments()
{
    return $this->comments->where('user_id', Auth::user()->id);
}

И я думаю, на ваш взгляд, у вас есть foreach для повторения всех сообщений, внутри вашего foreach вы загружаете комментарии к сообщениям, поэтому вы можете сделать это:

@foreach($posts as $post)
    $post->userComments()
@endforeach
person Vinicius Luiz    schedule 13.04.2017
comment
Я должен упомянуть, что результаты, которые я хочу вернуть, относятся к моему API, и поэтому я не использую блейд-представления. По этой причине мне нужно с нетерпением загружать результаты. - person user7863944; 13.04.2017