IN()
проверяет, находится ли значение в наборе значений, для любого сопоставленного значения затем возвращается значение true, не проверяется наличие всех значений,
Чтобы добиться того, что вы пытаетесь, вам нужно проверить каждый идентификатор тега отдельно, используя whereHas
, чтобы убедиться, что все они присутствуют
if ($request->has('tags')) {
$inputTags = $request->query('tags');
$tags = explode(',', $inputTags);
foreach($tags as $tag){
$query = $query->whereHas('tags', function($q) use ($tag) {
$q->where('id','=', $tag);
});
}
}