Reputation: 1170
I have an API to keep tracked photos and tags. Each photo can have N tags and one tag can be linked to N photos. That's done using 3 tables:
Now I'm working to get all photos tagged with a set of tags the idea is to make requests to my API with a list of tags and get a list of photos that has at least all the tags.
I've been trying with the whereIn
operator.
This is my code (now it's all hardcoded):
$photos = Photo::whereHas('tags', function (Builder $query) {
$query->whereIn('tag', ['a5', 'mate', 'Brillante']);
})->get();
return response()->json($photos, 200);
When I execute it it return all that photos that match one tag and I need only photos that hast all the requested tags (in this example a5, mate).
I'm working on Laravel 9.
Edit:
As Tim Lewis suggested I've tried looping:
$tags = array("a5", "mate", "Brilante");
$photoQuery = Photo::query();
foreach($tags as $tag) {
\Log::debug($tag);
$photoQuery->whereHas('tags', function($query) use ($tag) {
return $query->where('tag', $tag);
});
}
$photos = $photoQuery->get();
Now it's returning an empty list I think because is looking for Photos that only have the 3 tags I hardcoded on the array.
Edit 2:
It seems that those changes were right, but for some reason Postman was not showing me any results of those changes are the solutions to my issue.
Upvotes: 3
Views: 1757
Reputation: 29278
Since the whereIn()
method matches against any of the values provided, and not all, you'll need to modify this. Specificying a number of whereHas()
clauses, 1 for each Tag, should work:
$photoQuery = Photo::query();
foreach ($request->input('tags') as $tag) {
$photoQuery = $photoQuery->whereHas('tags', function ($query) use ($tag) {
return $query->where('tag', $tag);
});
}
$photos = $photoQuery->get();
Now, depending on the tags
being sent to your API (assuming through the $request
variable as a 'tags' => []
array), this query will include a whereHas()
clause for each Tag, and only return Photo
records that have all specified Tags.
Upvotes: 2