skip to Main Content

I have this code here simplified.

Post::whereDoesntHave('tags', function($query){
     $query->whereIn(tags.id, $tagIds);
})

Lets say that tagIds = [1,2,3]
My goal is to retrieve only Posts that do not contain all of those tags.
ex. if post has tags 1,2,3 , then it shouldn’t be retrieved, but if it has 1,2,3,4 then it should.Code above doesn’t return correct result. Appreciate any help.

2

Answers


  1. Maybe you forgot to put array $tagIds to your query. I hope it works

    Post::whereDoesntHave('tags', function ($query) use ($tagIds) {
         $query->whereIn('tags.id', $tagIds);
    })
    

    or

    Post::whereHas('tags', function ($query) use ($tagIds) {
         $query->whereNotIn('tags.id', $tagIds);
    })
    
    Login or Signup to reply.
  2. The query that would accomplish the examples you give is:

    use AppModelsPost;
    use IlluminateDatabaseEloquentBuilder;
    
    $tagIds = [1, 2, 3];
    
    Post::query()
        ->whereHas('tags', function (Builder $query) use ($tagIds): void {
            $query->whereKeyNot($tagIds);
        })
        ->get();
    

    But consider that this query just gives you those posts that has at least one tag that is not in the array. So, by example, a post with zero tags will be returned.

    If you don’t want that behavior, we need to make it a little bit more complex:

    Post::query()
        ->whereHas('tags', function (Builder $query) use ($tagIds): void {
            $query->whereKeyNot($tagIds);
        })
        ->orWhereHas('tags', function (Builder $query) use ($tagIds): void {
            $query->whereKey($tagIds);
        }, operator: '<', count: count($tagIds))
        ->get();
    

    This query gives you those posts that don’t have exactly the tags in the array.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search