Filters in Laravel with OOP Practices

Ashish Shakya
3 min readApr 26, 2021

Basically, to implement the resource filter API, we check the query parameters from the existing request and apply the corresponding query bindings (where clause) to our Model.

The normal way to implement the filter criteria seems like:

The normal way to return the filtered data for a resource.

This approach of returning filtered data would be applicable for small-sized applications only. If the application is booted with heavy sets of filter logic then we would have to add recurring IF logic in the controller itself. This makes our controller very bulky.

Now let's implement some OOP principles to extract and encapsulate the logic to its own separate classes.

  1. First, we create an abstract class named BaseFilter. We then add a apply() method with some logic inside it as shown below. We shall discuss its working mechanism later in this blog.

2. Create a separate filter class for integrating filter logic for a resource that extends the BaseFilter class. Before we had included the filter logic using nested IFs in the Controller class but now we extract them into individual methods.

Things to remember:

  • The name of the method must be the key of the query parameters of the URL.
  • The method name must be written in camelCase .
  • For eg, if the URL is some-url?ward=20&municipality=2 and we have to filter the resource by ward and municipality, then we need to create two methods naming ward() and municipality() respectively.

3. We then add a local scope in the Model class. This method accepts an instance of Eloquent Builder as a first parameter and sets of filtersas the second parameter. It simply instantiates the FilterClass which we had defined before in Step 2and calls itsapply()method.

4. Lastly, we can simply call the filterByscope of our Modelclass and pass all the query parameters as its arguments.

What is happening behind the scene?

  • First, in the controller class, we are returning the resource by binding the local scope to our builder (filterBy)which we had created in the model class. As a parameter, we pass the array of query parameters using request()->all() .
  • The filterBy scope then instantiate the FilterClass and calls its apply() method. Keep in mind that, when we instantiate the FilterClass , we need to pass the instance of query builder and the previous array of query parameters for the filters.
  • The filter class that we had created extends the BaseFilterclass. It includes individual methods where the logic for the filter is written.
  • The apply() method of the BaseFilterclass is built in such a way that it iterates over every query parameter from the current URL and calls the filter method defined in its subclasses.
  • These methods are later responsible for binding the where clause in the Eloquent builder.

Wow, there it is. A neat and clean way to create a filter API for any resource. If you have to implement similar logic for any other Entity, simply create a new Filter class that extends the BaseFilterclass and add a local scope to its related Model class.

--

--