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;
});

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.

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.