lacodix/laravel-model-filter

A Laravel package to filter, search and sort models with ease while fetching from database.
69,643 176
Install
composer require lacodix/laravel-model-filter
Latest Version:v4.10.2
PHP:^8.2
License:MIT
Last Updated:Sep 30, 2026
Links: GitHub  ·  Packagist
Maintainer: lacodix

laravel-model-filter

Latest Version on Packagist GitHub Tests Action Status GitHub Code Style Action Status Total Downloads

This package allows you to filter, search and sort models while fetching from database with ease. It contains additional functionality to use query strings to filter, search and sort.

With this package you can easily filter, search and sort your Eloquent models. It supports various filter types like strings, dates, numbers, and enums out of the box. You can also create complex custom filters to handle any specific database logic.

Additionally you can use the visualisation functionality of filters.

Documentation

You can find the entire documentation for this package on our documentation site

See our Upgrade Guide for information on how to upgrade from older versions.

Laravel Boost skill

The package includes a laravel-model-filter-development skill for agents working on filters, search, sorting, and their UI and tests. In an application using Laravel Boost, enable skills and select lacodix/laravel-model-filter when running php artisan boost:install. Boost then installs the skill for the selected skills-capable agents. The package's short Boost guideline points to it when guidelines are enabled.

Installation

composer require lacodix/laravel-model-filter

Basic Usage

Filter

Create your first filter

php artisan make:filter CreatedAfterFilter --type=date --field=created_at

Filters can be applied directly to models, but they can also be easily applied to relations and nested relations using the RunsOnRelation trait. This automatically wraps the filter logic in a whereHas closure and correctly qualifies the field names using the related table.

// Set the filter mode
// App\Models\Filters\CreatedAfterFilter
public FilterMode $mode = FilterMode::GREATER_OR_EQUAL;

// Apply this filter and the HasFilters trait to a Model
// App\Models\Post
use HasFilters;
protected array $filters = [
    CreatedAfterFilter::class,
];

// Somwhere in a controller, select all posts created after 1st of January 2023
Post::filter(['created_after_filter' => '2023-01-01'])->get();

// Do the same via query string by calling
// this url: https://.../posts?created_after_filter=2023-01-01
Post::filterByQueryString()->get();

Search

// add searchable fields and the IsSearchable trait to Model:
// App\Models\Post
use IsSearchable;
protected array $searchable = [
    'title',
    'content',
];

// Somewhere in controller, find all posts that contain "test" in title or content
Post::search('test')->get();

// Treat %, _ and database-specific wildcard characters as ordinary input
Post::searchLiteral('100%_complete')->get();

// Do the same via query string by calling
// this url: https://.../posts?search=test
Post::searchByQueryString()->get();

Visualize

All filters have a blade template that can visualize the filter with one or multiple input fields. To visualize all filters of a dedicated model you can use a blade component:

<x-lacodix-filter::model-filters :model="Post::class" />

Grouping

Sometimes you don't need all of the filters for all parts of a web application. Maybe there shall be different filters be available to the backend as in the frontend, or different user types shall be able to use different filters.

For such cases this package offers filter grouping when adding filters to models

protected array $filters = [
    'frontend' => [
        HotFilter::class,
    ],
    'backend' => [
        CreatedAfterFilter::class,
        PublishedFilter::class,
    ]
];

The groups can be used in the scopes

Post::filterByQueryString('frontend')->get()

or

Post::filter(['hot_filter' => 'hot'], 'frontend')->get();
Post::filter(['created_after_filter' => '2023-01-01'], 'backend')->get();

Preparing Filters for Integrations

Integrations that need to inspect applicable filters before changing a query can use the opt-in FilterPreparation service. It resolves fresh filter objects, applies the same selection, population, normalization, and validation rules as filter(), and returns only filters that are ready to be applied. Preparation itself never changes a query.

use Lacodix\LaravelModelFilter\Support\FilterPreparation;

$prepared = (new FilterPreparation)->prepare(
    model: new Post,
    values: $request->all(),
    group: 'backend',
    strictGroup: true,
);

foreach ($prepared as $filter) {
    // Inspect the fresh, populated filter instance.
}

See Opt-in Filter Preparation for strict group resolution, instance configuration, and the PreparedFilters API.

Metadata

Filters can carry free, serializable metadata for whoever renders them - a presentation hint on the filter, a picture or initials per option. The package stores it and never interprets it; filtering and the query string stay untouched.

(new BelongsToFilter('person_id'))
    ->setRelationModel(Person::class)
    ->setTitleColumn('name')
    ->meta(['presentation' => 'avatars'])
    ->optionMeta(fn (BelongsToFilter $filter) => Person::query()
        ->whereIn('id', $filter->options())
        ->get()
        ->mapWithKeys(fn (Person $person) => [$person->id => [
            'avatar' => $person->photo_url,
            'initials' => $person->initials,
            'subtitle' => $person->club?->name,
        ]])
        ->all());

$filter->getMeta();         // ['presentation' => 'avatars']
$filter->optionMetaFor(7);  // ['avatar' => ..., 'initials' => ..., 'subtitle' => ...]

meta() is available on every filter type and merges repeated calls; optionMeta() lives on SelectFilter (and its descendants) and OptionFilter, takes a closure for database-backed options and resolves it once per instance. See Filter Metadata for the contract and the avatar-filter use case.

Testing

composer test

Contributing

Please run the following commands and solve potential problems before committing and think about adding tests for new functionality.

composer rector:test
composer insights
composer csfixer:test
composer phpstan:test

Changelog

Please see CHANGELOG for more information on what has changed recently.

Credits

License

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

Related Packages

jedrzej/pimpable

Laravel 4/5/6 package that allows to dynamically filter, sort and eager load rel...

195,171 104
aldemeery/sieve

A simple, clean and elegant way to filter Eloquent models.

6,544 137
jedrzej/searchable

Searchable trait for Laravel's Eloquent models - filter your models using reques...

279,457 125
tucker-eric/eloquentfilter

An Eloquent way to filter Eloquent Models

5,466,677 1,766
moonofmylife/eloquentfilter

An Eloquent way to filter Eloquent Models

2,833 0