Demystifying Laravel Code: Adding Search Filters with Builder::macro
If you’re new to Laravel and find this code a bit daunting, don’t worry! We’ll break it down into simple parts to help you understand what’s going on. This code snippet is used in Laravel, a popular PHP web application framework, to add search filters to database queries. Let’s dive in.
Builder::macro('searchFilters', function ($attributes, string $searchTerm) {
$this->where(function (Builder $query) use ($attributes, $searchTerm) {
foreach (Arr::wrap($attributes) as $attribute) {
$query->when(
str_contains($attribute, '.'),
function (Builder $query) use ($attribute, $searchTerm) {
[$relationName, $relationAttribute] = explode('.', $attribute);
$query->orWhereHas($relationName, function (Builder $query) use ($relationAttribute, $searchTerm) {
$query->where($relationAttribute, 'LIKE', "%{$searchTerm}%");
});
},
function (Builder $query) use ($attribute, $searchTerm) {
$query->orWhere($attribute, 'LIKE', "%{$searchTerm}%");
}
);
}
});
return $this;
});
The Builder::macro Method
In Laravel, a “macro” is a way to add custom methods to classes. In this case, we are adding a custom method called searchFilters
to Laravel’s query builder (`Builder`) class.
Builder::macro('searchFilters', function ($attributes, string $searchTerm) {
// ... code ...
return $this;
});
Parameters
$attributes
: This is an array or a single attribute that you want to search in.$searchTerm
: The term you want to search for in the database.
The where
Method
Inside the searchFilters
method, you see a where
method being used. This method is used to build conditions for a database query.
$this->where(function (Builder $query) use ($attributes, $searchTerm) {
// ... code ...
});
Anonymous Function
Inside the where
method, we are defining an anonymous function (a function without a name). This function takes a $query
parameter, which represents the query builder instance.
Looping Through Attributes
Now, let’s look at what happens inside the anonymous function. We have a loop that goes through the provided attributes.
foreach (Arr::wrap($attributes) as $attribute) {
// ... code ...
}
Arr::wrap
The Arr::wrap
method is used to ensure that $attributes
is treated as an array, even if it’s a single value. This makes it easier to handle both single attributes and arrays of attributes consistently.
Checking for Relationships
Inside the loop, we check if an attribute contains a dot (`.`). If it does, it means we are dealing with a relationship in the database.
$query->when(
str_contains($attribute, '.'),
function (Builder $query) use ($attribute, $searchTerm) {
// Code for relationships
},
function (Builder $query) use ($attribute, $searchTerm) {
// Code for regular attributes
}
);
str_contains
The str_contains
function checks if the attribute contains a dot, indicating a relationship. If it does, we handle relationships; otherwise, we handle regular attributes.
Handling Relationships
If we are dealing with a relationship, we split the attribute into two parts: the relationship name and the attribute within the relationship.
[$relationName, $relationAttribute] = explode('.', $attribute);
Then, we use orWhereHas
to create a condition for searching within that relationship.
$query->orWhereHas($relationName, function (Builder $query) use ($relationAttribute, $searchTerm) {
$query->where($relationAttribute, 'LIKE', "%{$searchTerm}%");
});
Here, we are searching for records where the $relationAttribute
matches the $searchTerm
within the $relationName
relationship.
Handling Regular Attributes
If we are dealing with a regular attribute (no dot in the name), we use a simple orWhere
clause to create a search condition.
$query->orWhere($attribute, 'LIKE', "%{$searchTerm}%");
This code searches for records where the $attribute
matches the $searchTerm
.
Returning the Query Builder
Finally, after adding all these conditions, we return the modified query builder `$this`
to allow for further chaining of query builder methods.
In a nutshell, this code allows you to easily add search filters to your database queries in Laravel. It handles both regular attributes and relationships, making your search functionality flexible and powerful. As you become more familiar with Laravel, you’ll find these kinds of code snippets incredibly useful for building dynamic applications.
Subscribe to my newsletter
Read articles from RJ directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
RJ
RJ
My journey into the world of coding began 20 years ago, starting as a mere hobby and gradually transforming into a passion. Over the years, I've honed my skills meticulously, enabling me to offer effective solutions to the various challenges my clients encounter.