Laravel – получить вложенное отношение с «whereHas»

У меня три модели Period , Post, User:

  • period и posts имеют отношения M:N на period_posts

  • posts и user имеют отношения M:N на views

Модель периода:

class Period extends Model
{

    public $timestamps=false;

    public function posts()
    {
        return $this->belongsToMany(Post::class);
    }
}

Почтовая модель:

class Post extends Model
{
    public function periods()
    {
        return $this->belongsToMany(Period::class);
    }


    public function views()
    {
        return $this->belongsToMany(User::class, 'views')
            ->withTimestamps();
    }
}

Модель пользователя:

class User extends Authenticatable
{
use Notifiable;



  public function views()
  {
      return $this->belongsToMany(Post::class, 'views')
          ->withTimestamps();
  }
}

Таблица просмотров:

iduser_idpost_id

Мне нужно получить все periods со своими posts там, где auth user не видел (по отношениям просмотров)

Я пытался сделать это, но это не сработало:

    $period = Period::whereHas('posts.views', function ($users) {
        $users->where('user_id', auth()->Id());
    })->get();

Итак, вы должны получить все периоды с невидимыми сообщениями для аутентифицированного пользователя?

Roberto Ferro 11.07.2019 10:47

Таблица просмотров содержит только просмотренные посты?

Roberto Ferro 11.07.2019 11:20

таблица представлений содержит post_id и user_id ...другими словами, post имеет отношение m:n к user, используя views таблицу

Mortada Jafar 11.07.2019 11:26
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Поиск нового уровня в Laravel с помощью MeiliSearch и Scout
Поиск нового уровня в Laravel с помощью MeiliSearch и Scout
Laravel Scout - это популярный пакет, который предоставляет простой и удобный способ добавить полнотекстовый поиск в ваше приложение Laravel. Он...
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
5
3
1 883
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

Кажется, что ваши модели немного «запутаны», вы можете получить то, что хотите, с помощью Eloquent, но вам нужно разделить логику на несколько частей.

Пример:

// Get all user seen posts #1
$seenPosts = Auth::user()->views()->pluck('id');

// Get all user unseen posts with its period inside the collection #2
$posts = Post::whereNotIn('id',$seenPosts)->with('periods')->get(); 

у меня есть три отношения m:n .. у меня есть две сводные таблицы views и posts_period .. сообщения с точкой имеют отношение M:N не один ко многим

Mortada Jafar 11.07.2019 12:07

Хорошо, вы можете получить все с предыдущим кодом. Во-первых, вы должны получить все сообщения, просмотренные пользователями (#1). Затем вы можете получить все невидимые сообщения с их точками (# 2).

Roberto Ferro 11.07.2019 12:14

Вы можете использовать whereDoesntHave, я проверил на своем компьютере, и он работает хорошо:

$post_ids = Post::whereDoesntHave('views', function($q){
    $q->where('user_id',Auth::id());
})->get()->pluck('id');
$periods = Period::whereHas('posts', function($q) use($post_ids){
    $q->whereIn('post_id',$post_ids);
})->get();
dd($periods->pluck('id'));

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

View::where('user_id', '!=', Auth::user()->id)->groupBy('post_id')->whereHas('posts')->pluck('post_id');

Мое решение делает то же самое только с одним запросом:

Period::query()
      ->whereHas('posts', function ($query) {
        $query->whereHas('views', function ($query) {
          $query->where('users.id', '=', auth()->Id());
        }, '=', 0);
    });

Другие вопросы по теме