Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

weeniebeenie's avatar

What is the convention for creating named routes to 'filter' the index method/results?

Enjoying learning laravel with the beginners course but something not really covered was filtering, particularly with full routes.

I understand the 7 default methods on a controller, and index is where you'd return all your items, whatever they may be. But what if I want to filter those full results via a clean proper route, not a ?foo=bar query string? So they'd still be shown with the same view, exact same layout, but filtered by whatever.

For example in a blog or news website I might return all the unfiltered articles on the root or /articles but then also have filtered routes like:

  • /articles/{year} to get all articles published in X year
  • /articles/{author} to get all articles by X author
  • /articles/{category} to get all articles in X category

...and so on.

What would the broad approach to that be? Would you use the existing Article controller, or create a new one for each? That seems unlikely to be the best approach but the only similarlity in the video series I saw was when Jeffrey made the Tag controller for tags.

So far I've just tried to get /articles/{category} working by adding a category_id to the articles table, then a categories table with a name and foreign id, plus all required relationships in the models.

I can then get the results I want with $articles = $category->articles which works, but it's not eager loading like that and I seemingly can't chain things like paginate onto it like that either. So I then tried constructing a full Eloquent query but got stuck in the fact that the where clause I wanted was on the subtable, not the table of the Article model. i.e. I was passing the category word in the route (articles/opinion) rather than the id in the primary table. Couldn't work out how you'd manage that.

I think I went down a few too many rabbit holes via google as a beginner and confused myself, so some proper guidance on the general principles here would be very helpful! I feel like I must be overcomplicating what seems like a simple filtering action with a route.

0 likes
7 replies
martinbean's avatar

But what if I want to filter those full results via a clean proper route, not a ?foo=bar query string?

@weeniebeenie You wouldn’t. That’s literally the purpose of a query string. It’s why it is called a query string.

Use query string parameters to filter by a single criterion, or multiple criteria:

  • /articles?year=2024
  • /articles?author=martinbean
  • /articles?category=tutorials
  • /articles?year=2024&author=martinbean&category=tutorials
2 likes
Tray2's avatar

I agree with @martinbean, use the query string, that way you can check for it when you build your eloquent.

It could look something like this.

1 like
Snapey's avatar

also, your proposed routes would not work. Any passed parameter would be taken as a year

1 like
weeniebeenie's avatar

Yeah of course they were just to give an idea of what I meant, if it were real it'd be /articles/year/{year} and so on, so they don't clash.

Obviously functionally the end result on the page would be the same if I used query strings but I just prefer the cleaner looking urls.

If I were going to stubborn would a custom method for each one be the only way then? indexByCategory, indexByYear etc

Or maybe I could use query strings and rewrite the URL to the nicer ones? I seem to recall doing something like that when I wrote with vanilla PHP some years ago.

martinbean's avatar

If I were going to stubborn would a custom method for each one be the only way then? indexByCategory, indexByYear etc

@weeniebeenie And what about for the routes where you want to combine filters, i.e. filter by year and category? Are you then going to create methods for each combination (filterByYearAndCategory, filterByYearAndAuthor, filterByYearAuthorAndYearAndCategory, and so on)? Adding more filters is just going to exponentially increase the number of methods (and combinations) you need to support.

weeniebeenie's avatar

@martinbean yes it's a fair point. Looking through my entire planned site as you say it'd evidently not be sane to do except for a couple of simpler Boolean filters so I'll save myself more hours of pain and use query strings. Thanks.

1 like
Garet's avatar

I'm not sure if it helps at all, but in the interests of keeping things clean, I tend to create a separate class for the filtering.

Using the blog as an example, your BlogController would typically have an index method that would get all articles in date order and display them in a view.

What I've done is created a separate class called BlogSearch with a single method where I pass an array of parameters (search string, category, date, author id, etc).

From this method I return an instance of Illuminate\Database\Eloquent\Builder back to the controller's index method so I can then do pagination or any additional operations on the result.

Here's a simplified example:

BlogController.php

public function index(): View
{
    $query = BlogSearch::search($request->all());

    $blogs = $query->with(['image', 'meta'])
                   ->withCount('categories')
                   ->paginate(100);

    return view('blog.index', ['blogs' => $blogs]);
}

BlogSearch.php

public function search($params): Builder
{
    $query = Blog::query();

    if (isset($params['category_id'])) {
        $query->where('category_id', $params['category_id']);
    }

    if (isset($params['search'])) {
        $query->where('name', $params['search']);
    }

    return $query;
}
1 like

Please or to participate in this conversation.