PHPackages                             beratkara/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. beratkara/searchable

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

beratkara/searchable
====================

Eloquent model search trait.

1.13.0(6y ago)1120MITPHPPHP &gt;=5.4.0

Since Jun 17Pushed 5y agoCompare

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

READMEChangelogDependencies (1)Versions (57)Used By (0)

Searchable, a search trait for Laravel
======================================

[](#searchable-a-search-trait-for-laravel)

This package is forked from "nicolaslopezj/searchable" package
==============================================================

[](#this-package-is-forked-from-nicolaslopezjsearchable-package)

Installation
============

[](#installation)

Simply add the package to your `composer.json` file and run `composer update`.

```
"beratkara/searchable": "dev-master"

```

Usage
=====

[](#usage)

Add the trait to your model and your search rules.

```
use Nicolaslopezj\Searchable\SearchableTrait;

class User extends \Eloquent
{
    use SearchableTrait;

    /**
     * Searchable rules.
     *
     * @var array
     */
    protected $searchable = [
        /**
         * Columns and their priority in search results.
         * Columns with higher values are more important.
         * Columns with equal values have equal importance.
         *
         * @var array
         */
        'columns' => [
            'users.first_name' => 10,
            'users.last_name' => 10,
            'users.bio' => 2,
            'users.email' => 5,
            'posts.title' => 2,
            'posts.body' => 1,
        ],
        'joins' => [
            'posts' => ['users.id','posts.user_id'],
        ],
    ];

    public function posts()
    {
        return $this->hasMany('Post');
    }

}
```

Now you can search your model.

```
// Simple search
$users = User::search($query)->get();

// Search and get relations
// It will not get the relations if you don't do this
$users = User::search($query)
            ->with('posts')
            ->get();
```

Search Paginated
----------------

[](#search-paginated)

As easy as laravel default queries

```
// Search with relations and paginate
$users = User::search($query)
            ->with('posts')
            ->paginate(20);
```

Mix queries
-----------

[](#mix-queries)

Search method is compatible with any eloquent method. You can do things like this:

```
// Search only active users
$users = User::where('status', 'active')
            ->search($query)
            ->paginate(20);
```

Custom filters
--------------

[](#custom-filters)

```
// Restricted search

$filters = [
    [
        'type' => 'whereBetween',
        'column' => 'created_at',
        'data' => [
            Carbon::now()->startOfDay()->format('Y-m-d H:i:s'),
            Carbon::now()->endOfDay()->format('Y-m-d H:i:s')
        ]
    ]
];

$users = User::where('status', 'active')
            ->searchRestricted($query, $filters)
            ->paginate(20);
```

Custom Threshold
----------------

[](#custom-threshold)

The default threshold for accepted relevance is the sum of all attribute relevance divided by 4. To change this value you can pass in a second parameter to search() like so:

```
// Search with lower relevance threshold
$users = User::where('status', 'active')
            ->search($query, 0)
            ->paginate(20);
```

The above, will return all users in order of relevance.

Entire Text search
------------------

[](#entire-text-search)

By default, multi-word search terms are split and Searchable searches for each word individually. Relevance plays a role in prioritizing matches that matched on multiple words. If you want to prioritize matches that include the multi-word search (thus, without splitting into words) you can enable full text search by setting the third value to true. Example:

```
// Prioritize matches containing "John Doe" above matches containing only "John" or "Doe".
$users = User::search("John Doe", null, true)->get();
```

If you explicitly want to search for full text matches only, you can disable multi-word splitting by setting the fourth parameter to true.

```
// Do not include matches that only matched "John" OR "Doe".
$users = User::search("John Doe", null, true, true)->get();
```

How does it work?
=================

[](#how-does-it-work)

Searchable builds a query that search through your model using Laravel's Eloquent. Here is an example query

#### Eloquent Model:

[](#eloquent-model)

```
use Nicolaslopezj\Searchable\SearchableTrait;

class User extends \Eloquent
{
    use SearchableTrait;

    /**
     * Searchable rules.
     *
     * @var array
     */
    protected $searchable = [
        'columns' => [
            'first_name' => 10,
            'last_name' => 10,
            'bio' => 2,
            'email' => 5,
        ],
    ];

}
```

#### Search:

[](#search)

```
$search = User::search('Sed neque labore', null, true)->get();
```

#### Result:

[](#result)

```
select `users`.*,

-- If third parameter is set as true, it will check if the column starts with the search
-- if then it adds relevance * 30
-- this ensures that relevant results will be at top
(case when first_name LIKE 'Sed neque labore%' then 300 else 0 end) +

-- For each column you specify makes 3 "ifs" containing
-- each word of the search input and adds relevace to
-- the row

-- The first checks if the column is equal to the word,
-- if then it adds relevance * 15
(case when first_name LIKE 'Sed' || first_name LIKE 'neque' || first_name LIKE 'labore' then 150 else 0 end) +

-- The second checks if the column starts with the word,
-- if then it adds relevance * 5
(case when first_name LIKE 'Sed%' || first_name LIKE 'neque%' || first_name LIKE 'labore%' then 50 else 0 end) +

-- The third checks if the column contains the word,
-- if then it adds relevance * 1
(case when first_name LIKE '%Sed%' || first_name LIKE '%neque%' || first_name LIKE '%labore%' then 10 else 0 end) +

-- Repeats with each column
(case when last_name LIKE 'Sed' || last_name LIKE 'neque' || last_name LIKE 'labore' then 150 else 0 end) +
(case when last_name LIKE 'Sed%' || last_name LIKE 'neque%' || last_name LIKE 'labore%' then 50 else 0 end) +
(case when last_name LIKE '%Sed%' || last_name LIKE '%neque%' || last_name LIKE '%labore%' then 10 else 0 end) +

(case when bio LIKE 'Sed' || bio LIKE 'neque' || bio LIKE 'labore' then 30 else 0 end) +
(case when bio LIKE 'Sed%' || bio LIKE 'neque%' || bio LIKE 'labore%' then 10 else 0 end) +
(case when bio LIKE '%Sed%' || bio LIKE '%neque%' || bio LIKE '%labore%' then 2 else 0 end) +

(case when email LIKE 'Sed' || email LIKE 'neque' || email LIKE 'labore' then 75 else 0 end) +
(case when email LIKE 'Sed%' || email LIKE 'neque%' || email LIKE 'labore%' then 25 else 0 end) +
(case when email LIKE '%Sed%' || email LIKE '%neque%' || email LIKE '%labore%' then 5 else 0 end)

as relevance
from `users`
group by `id`

-- Selects only the rows that have more than
-- the sum of all attributes relevances and divided by 4
-- Ej: (20 + 5 + 2) / 4 = 6.75
having relevance > 6.75

-- Orders the results by relevance
order by `relevance` desc
```

###  Health Score

33

—

LowBetter than 75% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity11

Limited adoption so far

Community19

Small or concentrated contributor base

Maturity72

Established project with proven stability

 Bus Factor1

Top contributor holds 67.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 ~39 days

Recently: every ~149 days

Total

55

Last Release

2239d ago

Major Versions

0.1.2 → 1.0.02014-06-17

### Community

Maintainers

![](https://www.gravatar.com/avatar/9e90c83dcf8b2e3e2df2b8e63195ae55a02f46b238ef2ef0754f40e7fc5edb58?d=identicon)[beratkara](/maintainers/beratkara)

---

Top Contributors

[![nicolaslopezj](https://avatars.githubusercontent.com/u/2042567?v=4)](https://github.com/nicolaslopezj "nicolaslopezj (106 commits)")[![jarnovanleeuwen](https://avatars.githubusercontent.com/u/1358997?v=4)](https://github.com/jarnovanleeuwen "jarnovanleeuwen (5 commits)")[![rjorel](https://avatars.githubusercontent.com/u/12407789?v=4)](https://github.com/rjorel "rjorel (3 commits)")[![kordero](https://avatars.githubusercontent.com/u/1572159?v=4)](https://github.com/kordero "kordero (3 commits)")[![tomzx](https://avatars.githubusercontent.com/u/188960?v=4)](https://github.com/tomzx "tomzx (3 commits)")[![joostbaptist](https://avatars.githubusercontent.com/u/8181757?v=4)](https://github.com/joostbaptist "joostbaptist (3 commits)")[![JulienTant](https://avatars.githubusercontent.com/u/785518?v=4)](https://github.com/JulienTant "JulienTant (3 commits)")[![svrnm](https://avatars.githubusercontent.com/u/1519757?v=4)](https://github.com/svrnm "svrnm (2 commits)")[![caiokawasaki](https://avatars.githubusercontent.com/u/9747004?v=4)](https://github.com/caiokawasaki "caiokawasaki (2 commits)")[![iget-master](https://avatars.githubusercontent.com/u/9434959?v=4)](https://github.com/iget-master "iget-master (2 commits)")[![kerwitz](https://avatars.githubusercontent.com/u/105719?v=4)](https://github.com/kerwitz "kerwitz (2 commits)")[![manavo](https://avatars.githubusercontent.com/u/259487?v=4)](https://github.com/manavo "manavo (2 commits)")[![MangTomas23](https://avatars.githubusercontent.com/u/14972551?v=4)](https://github.com/MangTomas23 "MangTomas23 (2 commits)")[![n1crack](https://avatars.githubusercontent.com/u/712404?v=4)](https://github.com/n1crack "n1crack (2 commits)")[![OmarMakled](https://avatars.githubusercontent.com/u/3720473?v=4)](https://github.com/OmarMakled "OmarMakled (2 commits)")[![osugregor](https://avatars.githubusercontent.com/u/781984?v=4)](https://github.com/osugregor "osugregor (2 commits)")[![jsdecena](https://avatars.githubusercontent.com/u/2285625?v=4)](https://github.com/jsdecena "jsdecena (1 commits)")[![billmn](https://avatars.githubusercontent.com/u/779534?v=4)](https://github.com/billmn "billmn (1 commits)")[![bmitzkus](https://avatars.githubusercontent.com/u/11650559?v=4)](https://github.com/bmitzkus "bmitzkus (1 commits)")[![changeweb](https://avatars.githubusercontent.com/u/9896315?v=4)](https://github.com/changeweb "changeweb (1 commits)")

---

Tags

searchlaraveldatabasemodeleloquentsearchable

### Embed Badge

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

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

###  Alternatives

[nicolaslopezj/searchable

Eloquent model search trait.

2.0k2.7M35](/packages/nicolaslopezj-searchable)[jedrzej/searchable

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

127259.1k5](/packages/jedrzej-searchable)

PHPackages © 2026

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