It's because you're using whereHas and whereDoesntHave on the same relationship. You should only pick one of them. in this case whereHas('categories') makes the most sense here ;)
Mar 7, 2020
8
Level 1
Relationship query Issue
I did this query :
http://127.0.0.1:8000/api/auth/products?filter[category]=1
Result: It returns the product with no category as well and
the first one with category not matching to queried one.
{
"data": [
{
"id": "51",
"name": "test",
"cats": [ ],
"imageUrl": "17ca4da-eed-4061-e45-4bb343a8e27.jpeg"
},
{
"id": "51",
"name": "test",
"cats": [
{
"id": 2,
"name": "Cleta Roberts MD",
}
],
"imageUrl": "124ca4da-ec2f-4061-b472-84bb103a8e27.jpeg"
},
{
"id": "46",
"name": "atque",
"cats": [
{
"id": 1,
"name": "Wyman Schumm",
},
{
"id": 2,
"name": "Cleta Roberts MD",
},
{
"id": 5,
"name": "Gay Kerluke",
}
],
"imageUrl": "none"
},
{
"id": "48",
"name": "quam",
"cats": [
{
"id": 1,
"name": "Wyman Schumm",
},
{
"id": 4,
"name": "Tremaine Walter",
},
{
"id": 5,
"name": "Gay Kerluke",
}
],
"imageUrl": "none"
},
{
"id": "37",
"name": "aliquid",
"cats": [
{
"id": 1,
"name": "Wyman Schumm",
},
{
"id": 2,
"name": "Cleta Roberts MD",
},
{
"id": 5,
"name": "Gay Kerluke",
}
],
"imageUrl": "none"
},
{
"id": "32",
"name": "qui",
"cats": [
{
"id": 1,
"name": "Wyman Schumm",
},
{
"id": 2,
"name": "Cleta Roberts MD",
},
{
"id": 4,
"name": "Tremaine Walter",
}
],
"imageUrl": "none"
},
{
"id": "24",
"name": "accusantium",
"cats": [
{
"id": 1,
"name": "Wyman Schumm",
},
{
"id": 3,
"name": "Wilfred Franecki",
},
{
"id": 5,
"name": "Gay Kerluke",
}
],
"imageUrl": "none"
},
{
"id": "3",
"name": "corrupti",
"cats": [
{
"id": 1,
"name": "Wyman Schumm",
}
],
"imageUrl": "none"
},
{
"id": "10",
"name": "et",
"cats": [
{
"id": 1,
"name": "Wyman Schumm",
}
],
"imageUrl": "none"
}
]
}
I have a scope in Product
public function scopeCategory($query, $filters)
{
return $query->with(['categories'])
->whereHas('categories', function ($query) use ($filters) {
$query->where('categories.id', $filters);
})
->whereDoesntHave('categories', function ($query) use ($filters) {
$query->where('categories.id', '!=', $filters);
})
;
}
called by
$products = QueryBuilder::for(Product::class)
->allowedFilters(['name', 'user_id', AllowedFilter::scope('category')])
->allowedSorts('id')
->latest()
->whereRaw('(quantity - total_sold) > 0')
->orWhere('created_at', '>=', Carbon::now()->subWeek())
->get();
return ProductCollection::collection($products);
Level 88
Yeah, @sswifto is correct here. You only now check which products have the correct categories, but then it loads all the categories of those products. Instead, you need to do this
$callback = function ($query) use ($filters) {
$query->where('categories.id', $filters);
};
return $query->with(['categories' => $callback])
->whereHas('categories', $callback);
Does this make sense to you? Now we're only loading the categories we're actually looking for instead of all categories of a product.
1 like
Please or to participate in this conversation.