Search posts by tags
P粉323050780
P粉323050780 2024-04-03 22:38:54
0
1
705

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?

P粉323050780
P粉323050780

reply all(1)
P粉596161915

GET requests using query strings can accept multiple parameters. instead of ?tag=test&unit (which won't really work anyway, since &unit will be parsed as $request->input('unit'), and will be null, & are reserved characters), you can send it as:

http://127.0.0.1:8000/posts?tags[]=test&tags[]=unit

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()
  ]);
}
  • Adjust the query to handle multiple values ​​using whereIn()
  • Use request()->input('tags', []) to access ?tags[]=...&tags[]=..., if not Provided is an empty array.
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template