PHPackages                             testmonitor/eloquent-searchable - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. testmonitor/eloquent-searchable

ActiveLibrary[Database &amp; ORM](/categories/database)

testmonitor/eloquent-searchable
===============================

A Laravel package that adds search functionality to Eloquent models, allowing for various search techniques such as exact and partial matches.

v1.1.0(1y ago)0785↓50%3MITPHPPHP ^8.2

Since Aug 28Pushed 6mo ago2 watchersCompare

[ Source](https://github.com/testmonitor/eloquent-searchable)[ Packagist](https://packagist.org/packages/testmonitor/eloquent-searchable)[ RSS](/packages/testmonitor-eloquent-searchable/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (2)DependenciesVersions (4)Used By (0)

Eloquent Searchable
===================

[](#eloquent-searchable)

[![Latest Stable Version](https://camo.githubusercontent.com/97ca5a1f9544bda10f26939978c829e043f0ce474d9411f8b8e175217c2f157a/68747470733a2f2f706f7365722e707567782e6f72672f746573746d6f6e69746f722f656c6f7175656e742d73656172636861626c652f762f737461626c65)](https://packagist.org/packages/testmonitor/eloquent-searchable)[![codecov](https://camo.githubusercontent.com/2d5fa3f80bae4719ad89df4b65af9d6727ffe22c7aefce93bb6992b78bdf90dd/68747470733a2f2f636f6465636f762e696f2f67682f746573746d6f6e69746f722f656c6f7175656e742d73656172636861626c652f67726170682f62616467652e7376673f746f6b656e3d454b3849574b36523947)](https://codecov.io/gh/testmonitor/eloquent-searchable)[![StyleCI](https://camo.githubusercontent.com/8de60fc42999f169531f9c1cb5b07625ac5a765568afe35939e7da12db2304f8/68747470733a2f2f7374796c6563692e696f2f7265706f732f3832343930393737392f736869656c64)](https://styleci.io/repos/824909779)[![License](https://camo.githubusercontent.com/854a0712ab4de0e359f1be30c54c45bc6007d00e4d32bf1982255405b38501cf/68747470733a2f2f706f7365722e707567782e6f72672f746573746d6f6e69746f722f656c6f7175656e742d73656172636861626c652f6c6963656e7365)](https://packagist.org/packages/eloquent-searchable)

A package that provides a search feature for Eloquent models. You can define SearchAspects for your Eloquent model that use different search techniques, such as an exact match or partial match.

It is heavily inspired by Spatie's [Query Builder](https://github.com/spatie/laravel-query-builder/) and can be used in conjunction with this package.

Table of Contents
-----------------

[](#table-of-contents)

- [Installation](#installation)
- [Usage](#usage)
    - [Aspects](#aspects)
    - [Search weighing](#search-weighing)
    - [Search related models](#search-related-models)
- [Tests](#tests)
- [Changelog](#changelog)
- [Contributing](#contributing)
- [Credits](#credits)
- [License](#license)

Installation
------------

[](#installation)

This package can be installed through Composer:

```
$ composer require testmonitor/eloquent-searchable
```

Next, publish the configuration file:

```
$ php artisan vendor:publish --tag=eloquent-searchable
```

The configuration file allows you the change the HTTP parameter name as well as the minimal query length.

Usage
-----

[](#usage)

To add searchable functionality to your Eloquent model, follow these steps:

1. Use the trait `TestMonitor\Searchable\Searchable` in your model(s).
2. Include the searchUsing scope together with one or more SearchAspects.

Add the searchable trait on the models you want to make searchable:

```
use Illuminate\Database\Eloquent\Model;
use TestMonitor\Searchable\Searchable;

class User extends Model
{
    use Searchable;

    // ...
}
```

Next, include the `searchUsing` scope with `SearchAspects` to define your search strategy:

```
use App\Models\User;
use Illuminate\Routing\Controller;
use TestMonitor\Searchable\Aspects\SearchAspect;

class UsersController extends Controller
{
    public function index()
    {
        return User::query()
            ->seachUsing([
                SearchAspect::exact('first_name'),
                SearchAspect::exact('last_name'),
                SearchAspect::partial('email'),
            ])
            ->get();
    }
}
```

In this example, the controller provides a way to search through a set of users:

- Both the first and last names are searched using the “exact” strategy. Only exact matches will be returned.
- The email field is searched using the “partial” match strategy. When the query term occurs within the email address, it will be returned.

The search query is automatically derived from the HTTP request. You can modify the HTTP query parameter in the configuration file. By default, the name `query` is used.

### Aspects

[](#aspects)

A model's search strategy is defined by search aspects. An aspect defines a matching configuration. For example, the exact search aspect perfoms an exact search on the provided attribute.

Eloquent Searcheable provides multiple aspects out of the box. Additionally, you can also define your own matching configuration using the custom aspect.

#### Exact match

[](#exact-match)

The Exact search aspect will only return matches that are equal to the search term.

```
use App\Models\Post;
use Illuminate\Routing\Controller;
use TestMonitor\Searchable\Aspects\SearchAspect;

class PostsController extends Controller
{
    public function index()
    {
        return Post::query()
            ->seachUsing([
                SearchAspect::exact(name: 'title'),
            ])
            ->get();
    }
}
```

#### Partial match

[](#partial-match)

The Partial search aspect returns matches where the search query occurs anywhere within the given attribute.

```
use App\Models\Post;
use Illuminate\Routing\Controller;
use TestMonitor\Searchable\Aspects\SearchAspect;

class PostsController extends Controller
{
    public function index()
    {
        return Post::query()
            ->seachUsing([
                SearchAspect::partial(name: 'title'),
            ])
            ->get();
    }
}
```

#### JSON match

[](#json-match)

The JSON search aspect returns matches where the search query occurs anywhere within the given JSON attribute.

```
use App\Models\Post;
use Illuminate\Routing\Controller;
use TestMonitor\Searchable\Aspects\SearchAspect;

class PostsController extends Controller
{
    public function index()
    {
        return Post::query()
            ->seachUsing([
                SearchAspect::json(name: 'settings'),
            ])
            ->get();
    }
}
```

#### Prefix match

[](#prefix-match)

The Prefix aspect combines the exact and partial strategy with the ability to strip one or more characters from the search query. This can be useful when your application provides an incremental code with a prefix to your user (say, ISSUE-12), but only store the number in your database (which would be the number 12).

As a default, the partial match strategy is used. Using the `exact` parameter, you can enable exact matching.

```
use App\Models\Issue;
use Illuminate\Routing\Controller;
use TestMonitor\Searchable\Aspects\SearchAspect;

class IssuesController extends Controller
{
    public function index()
    {
        return Issue::query()
            ->seachUsing([
                SearchAspect::prefix(name: 'code', prefix: 'ISSUE-', exact: true),
                SearchAspect::prefix(name: 'code', prefix: 'ISSUE-'),
            ])
            ->get();
    }
}
```

#### Custom aspect

[](#custom-aspect)

You can create your own search aspect by creating a class that implements the `TestMonitor\Searchable\Contracts\Search` contract.

Let's implement a new search aspect: a strategy that matches the beginning of an attribute. Your custom search aspect would look something like this:

```
use TestMonitor\Searchable\Weights;
use Illuminate\Database\Eloquent\Builder;
use TestMonitor\Searchable\Contracts\Search;

class StartsWithSearch implements Search
{
    /**
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @param \TestMonitor\Searchable\Weights $weights
     * @param string $property
     * @param string $term
     * @param int $weight
     */
    public function __invoke(Builder $query, Weights $weights, string $property, string $term, int $weight = 1): void
    {
        $query->where($property, 'like', "{$term}%");
    }
}
```

To use this custom aspect, define it in your search criteria like this:

```
use App\Models\Post;
use Illuminate\Routing\Controller;
use App\Search\Aspects\CustomSearch;
use TestMonitor\Searchable\Aspects\SearchAspect;

class PostsController extends Controller
{
    public function index()
    {
        return Post::query()
            ->seachUsing([
                SearchAspect::custom('name', new CustomSearch),
            ])
            ->get();
    }
}
```

### Search weighing

[](#search-weighing)

Optionally, you can use search weights. Weighing prioritizes search criteria, placing results with higher weights at the top.

Let's make a Post model searchable and use the following criteria:

- A partial keyword match in the post's title should be ranked highest.
- A partial keyword match in the summary should be ranked below any title match.
- A partial keyword match in the description should be ranked below any other criteria.

Here's an example that implements these criteria:

```
use App\Models\Post;
use Illuminate\Routing\Controller;
use TestMonitor\Searchable\Aspects\SearchAspect;

class PostsController extends Controller
{
    public function index()
    {
        return Post::query()
            ->seachUsing([
                SearchAspect::partial(name: 'title', weight: 20),
                SearchAspect::partial(name: 'summary', weight: 10),
                SearchAspect::partial('description'),
            ])
            ->get();
    }
}
```

### Search related models

[](#search-related-models)

Use dotted notation to search through related model attributes.

Let's say you want to search your posts based on their blog's title and description. Here's an example that implements these criteria:

```
use App\Models\Post;
use Illuminate\Routing\Controller;
use TestMonitor\Searchable\Aspects\SearchAspect;

class PostsController extends Controller
{
    public function index()
    {
        return Post::query()
            ->seachUsing([
                SearchAspect::exact('blog.title'),
                SearchAspect::partial('blog.description'),
            ])
            ->get();
    }
}
```

Tests
-----

[](#tests)

The package contains integration tests. You can run them using PHPUnit.

```
$ vendor/bin/phpunit

```

Changelog
---------

[](#changelog)

Refer to [CHANGELOG](CHANGELOG.md) for more information.

Contributing
------------

[](#contributing)

Refer to [CONTRIBUTING](CONTRIBUTING.md) for contributing details.

Credits
-------

[](#credits)

- [Thijs Kok](https://www.testmonitor.com/)
- [Stephan Grootveld](https://www.testmonitor.com/)
- [Frank Keulen](https://www.testmonitor.com/)
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Refer to the [License](LICENSE.md) for more information.

###  Health Score

39

—

LowBetter than 86% of packages

Maintenance58

Moderate activity, may be stable

Popularity19

Limited adoption so far

Community14

Small or concentrated contributor base

Maturity54

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 58.1% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~133 days

Total

2

Last Release

404d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/39f48c881813b7d3b044ca5660aa5ab9e60b5dd7c34ed4a47acbb11bd20b7593?d=identicon)[thijskok](/maintainers/thijskok)

---

Top Contributors

[![thijskok](https://avatars.githubusercontent.com/u/1344550?v=4)](https://github.com/thijskok "thijskok (36 commits)")[![stefanius](https://avatars.githubusercontent.com/u/2707905?v=4)](https://github.com/stefanius "stefanius (21 commits)")[![Frankisgek](https://avatars.githubusercontent.com/u/487218?v=4)](https://github.com/Frankisgek "Frankisgek (4 commits)")[![StyleCIBot](https://avatars.githubusercontent.com/u/11048387?v=4)](https://github.com/StyleCIBot "StyleCIBot (1 commits)")

---

Tags

searchlaravelmodeleloquenttestmonitor

### Embed Badge

![Health badge](/badges/testmonitor-eloquent-searchable/health.svg)

```
[![Health](https://phpackages.com/badges/testmonitor-eloquent-searchable/health.svg)](https://phpackages.com/packages/testmonitor-eloquent-searchable)
```

###  Alternatives

[tucker-eric/eloquentfilter

An Eloquent way to filter Eloquent Models

1.8k4.8M26](/packages/tucker-eric-eloquentfilter)[jedrzej/searchable

Searchable trait for Laravel's Eloquent models - filter your models using request parameters

127259.1k5](/packages/jedrzej-searchable)[lacodix/laravel-model-filter

A Laravel package to filter, search and sort models with ease while fetching from database.

17649.9k](/packages/lacodix-laravel-model-filter)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
