Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel - Get nested relation with "whereHas"

I have three models Period , Post, User:

  • period and posts have M:N relationship on period_posts

  • posts and user have M:N relationship on views

Period Model:

class Period extends Model
{

    public $timestamps=false;

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

Post Model:

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


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

User Model:

class User extends Authenticatable
{
use Notifiable;



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

views Table:

id user_id post_id

I need to get all periods with its posts where auth user have not seen (by views relationship)

I tried to do this but that did not work :

    $period = Period::whereHas('posts.views', function ($users) {
        $users->where('user_id', auth()->Id());
    })->get();
like image 429
Mortada Jafar Avatar asked Jul 08 '19 07:07

Mortada Jafar


2 Answers

Seems that your models are a little bit "messy" you can get what you want with Eloquent but you've to split the logic into a few parts.

Example:

// 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(); 
like image 111
Roberto Ferro Avatar answered Oct 18 '22 20:10

Roberto Ferro


You can use whereDoesntHave, I tested in my computer, and it runs well:

$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'));
like image 24
protoproto Avatar answered Oct 18 '22 21:10

protoproto