altrntv/eloquent-filter

Eloquent Filter for Laravel Models.

Installs: 3

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Watchers: 0

Forks: 0

Open Issues: 0

pkg:composer/altrntv/eloquent-filter

v1.0.1 2025-11-10 08:38 UTC

This package is auto-updated.

Last update: 2025-11-10 08:41:25 UTC


README

Latest Version Total Downloads

Eloquent Filter provides a clean and expressive way to apply dynamic, request-driven filters to your Eloquent models. It automatically maps incoming request parameters to filter methods, making complex query filtering simple and maintainable.

Table of Contents

Requirements

This package requires:

  • PHP ^8.3
  • Laravel ^12.0

Installation

Install the package via Composer:

composer require altrntv/eloquent-filter

Basic Usage Filters

Extend your model with the Filterable trait:

use Altrntv\EloquentFilter\Traits\Filterable;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Foundation\Auth\User as Authenticatable;

/**
 * @method static Builder<static>|self filter(array<string, mixed> $parameters)
 * @method static Builder<static>|self filterByRequest()
 */
class User extends Authenticatable
{
    use Filterable;
}

After adding the trait, your model gains two new query builder methods:

  • filter(array $parameters) — Applies filters using a key-value array.
  • filterByRequest() — Automatically applies filters from the current HTTP request, using the key defined in your configuration.

Creating a Filter Class

You can create a filter class using the Artisan command:

php artisan make:eloquent-filter UserFilter

Then, define methods corresponding to each filterable parameter. Each method should accept a value and modify the query builder accordingly.

use Altrntv\EloquentFilter\Filters\EloquentFilter;
use Illuminate\Database\Eloquent\Builder;

class UserFilter extends EloquentFilter
{
    public function name(string $value): Builder
    {
        return $this->builder
            ->whereLike('name', "%{$value}%");
    }

    public function age(string $value): Builder
    {
        return $this->builder
            ->where('age', '>=', $value);
    }
}

Controller Example

use App\Models\User;
use App\Http\Requests\UserIndexRequest;
use Illuminate\Http\JsonResponse;

final class UserController extends Controller
{
    public function index(UserIndexRequest $request): JsonResponse
    {
        $users = User::query()
            ->filterByRequest()
            ->get();
    
        return $users->toResourceCollection();
    }
}

Validating Filters

It’s recommended to validate incoming filter parameters in your request class:

use Illuminate\Foundation\Http\FormRequest;

class UserIndexRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'filter.name' => ['string', 'max:255'],
            'filter.age' => ['integer', 'min:0', 'max:150'],
        ];
    }
}

Casting Filter Values

Eloquent Filter supports the following cast types: integer, string, boolean, and array.

To cast a value, define it in the $casts property of your filter:

use Altrntv\EloquentFilter\Filters\EloquentFilter;
use Illuminate\Database\Eloquent\Builder;

class UserFilter extends EloquentFilter
{
    protected array $casts = [
        'age' => 'integer',
        'roles' => 'array',
    ];

    public function age(int $value): Builder
    {
        return $this->builder
            ->where('age', '>=', $value);
    }

    public function roles(array $value): Builder
    {
        return $this->builder
            ->whereIn('roles', $value);
    }
}

And in your form request:

use Illuminate\Foundation\Http\FormRequest;

class UserIndexRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'filter.name' => ['string', 'max:255'],
            'filter.age' => ['integer', 'min:0', 'max:150'],
            'filter.roles' => ['string', 'regex:/^\d+(,\d+)*$/'],
        ];
    }
}

A typical request might look like this:

GET /users?filter[name]=John&filter[age]=18&filter[roles]=1,2,4

Joining Parameters

Sometimes multiple request parameters represent a single logical concept. For example, vip_at_from and vip_at_to form a date range.

Eloquent Filter allows you to group multiple parameters under a single key using the $joinParameters property.

All keys inside the group are:

  • converted to camelCase (e.g., vip_at_fromvipAtFrom),
  • passed to your filter method via argument unpacking (...), so the method’s argument names must match the camelCased keys.

Example Filter Class

use Altrntv\EloquentFilter\Filters\EloquentFilter;
use Illuminate\Database\Eloquent\Builder;

class UserFilter extends EloquentFilter
{
    protected array $joinParameters = [
        'vip_at' => ['vip_at_from', 'vip_at_to'],
    ];

    public function vipAt(string $vipAtFrom, string $vipAtTo): Builder
    {
        return $this->builder
            ->where(function (Builder $query) use ($vipAtFrom, $vipAtTo) {
                $query
                    ->whereDate('vip_from', '<=', $vipAtTo)
                    ->whereDate('vip_to', '>=', $vipAtFrom);
            });;
    }
}

Request Example

GET /users?filter[vip_at_from]=2024-01-01&filter[vip_at_to]=2024-12-31

Transformed Parameters

$this->parameters = [
    'vip_at' => [
        'vipAtFrom' => '2024-01-01',
        'vipAtTo' => '2024-12-31',
    ],
]

This approach is especially useful for handling ranges or multipart filters, keeping your request parameters clean and your filter methods readable.

Basic Usage Sorts

Eloquent Filter now supports sorting via the Sortable trait and EloquentSort classes. This allows you to apply dynamic sorting based on HTTP requests or string parameters.

Extend your model with the Sortable trait:

use Altrntv\EloquentFilter\Traits\Sortable;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Foundation\Auth\User as Authenticatable;

/**
 * @method static Builder<static>|self sort(string $parameters)
 * @method static Builder<static>|self sortByRequest()
 */
class User extends Authenticatable
{
    use Sortable;
}

After adding the trait, your model gains two query builder methods:

  • sort(string $parameters) — Apply sorting using a comma-separated string of columns.
  • sortByRequest() — Automatically applies sorting from the current HTTP request, using the key defined in your configuration.

Creating a Sort Class

You can create a sort class using the Artisan command:

php artisan make:eloquent-sort UserSort
use Altrntv\EloquentFilter\Filters\EloquentSort;
use Illuminate\Database\Eloquent\Builder;

class UserSort extends EloquentSort
{
    public function name(string $direction): Builder
    {
        return $this->builder
            ->orderBy('name', $direction);
    }

    public function age(string $direction): Builder
    {
        return $this->builder
            ->orderBy('age', $direction);
    }
}

Request Example

GET /users?sort_by=name,-age
  • name — ascending
  • -age — descending

The sort string is split by the configured separator (, by default), and the direction is inferred from the - prefix.

Applying Sort

In controller:

$users = User::query()
    ->sortByRequest()
    ->get();

Or using a manual string:

$users = User::query()
    ->sort('name,-age')
    ->get();

Testing

composer test

Contributing

Contributions are welcome! If you’d like to improve this package, please fork the repository and open a pull request. Bug fixes, new features, and documentation improvements are all appreciated.

Credits

License

The MIT License (MIT). Please see License File for more information.