I need to display posts by tags. My solution works for a single tag like this:
route:
Route::get('/posts',
[PostController::class, 'index'])->middleware('auth');
Post model filter:
public function scopeFilter($query, array $filters)
{
if ($filters['tag'] ?? false) {
$tagId = Tag::where('name', $filters['tag'])->first()->id;
$query->whereHas('tags', function($q) use ($tagId) {
$q->where('tag_id', $tagId);
});
}
}
Method index of PostController:
public function index()
{
return view('posts', [
'posts' => Post::latest()->filter(request(['tag']))->get()
]);
}
This code applies to the following URL: "http://127.0.0.1:8000/posts/?tag=test". But I need to find a way to search for posts with more tags, for example I want to find posts with tags "test" and "unit". To do this I want to use a URL like this: "http://127.0.0.1:8000/posts/?tag=test&unit". I'm stuck because I thought "request(['tag'])" would return "test&unit" but it only returns "test". Is it possible to somehow get the "unit" tag from this request?
GETrequests using query strings can accept multiple parameters. instead of?tag=test&unit(which won't really work anyway, since&unitwill be parsed as$request->input('unit'), and will benull,&are reserved characters), you can send it as:On the backend, when you access
request()->input('tags'), you get the following array:$tags = request()->input('tags'); // ['test', 'unit']So, put them together:
// ScopeFilter method on your `Post` Model public function scopeFilter($query, array $tagNames) { if (!empty($tagNames)) { $tagIds = Tag::whereIn('name', $tagNames)->pluck('id'); return $query->whereHas('tags', function($subQuery) use ($tagIds) { return $subQuery->whereIn('tags.id', $tagIds); }); // Alternative without `$tagIds`, using `$tagNames` directly // return $query->whereHas('tags', function($subQuery) use ($tagNames) { // return $subQuery->whereIn('tags.name', $tagNames); // }); } return $query; } // Usage public function index() { return view('posts', [ 'posts' => Post::latest()->filter(request()->input('tags', []))->get() ]); }whereIn()request()->input('tags', [])to access?tags[]=...&tags[]=..., if not Provided is an empty array.