PHPackages                             maestrodimateo/laravel-search - 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. maestrodimateo/laravel-search

ActiveLibrary

maestrodimateo/laravel-search
=============================

Multi-criteria search trait for Laravel Eloquent models

1.0.0(1mo ago)15—0%MITPHPPHP ^8.3 || ^8.4

Since Mar 19Pushed 1mo agoCompare

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

READMEChangelogDependencies (4)Versions (2)Used By (0)

Laravel Search
==============

[](#laravel-search)

A Laravel package for simple and multi-column search on Eloquent models, with native support for JSON fields and PostgreSQL / MySQL dialects.

---

When to use this package
------------------------

[](#when-to-use-this-package)

This package is a good fit when:

- **You store structured data as JSON columns** — e.g. an `apprenant` column holding `{ "nom": "Dupont", "prenom": "Jean" }`. Native Eloquent search does not handle JSON path extraction out of the box, and writing raw `->>'key'` syntax every time is error-prone.
- **You need to search across multiple columns at once** — instead of chaining multiple `orWhere` calls, you declare your columns once in `getFullTextColumns()` and call a single scope.
- **Your application targets both PostgreSQL and MySQL** — the package transparently switches between `ILIKE` / `->>` (PostgreSQL) and `LIKE` / `->>'$.path'` (MySQL) with no change to your model code.
- **You want a lightweight solution with no external dependencies** — no Elasticsearch, no Meilisearch, no extra infrastructure. Everything runs on your existing database.

This package is **not** the right choice when:

- You need **relevance ranking** or full-text scoring (use PostgreSQL `tsvector` or a dedicated search engine instead).
- Your tables have **millions of rows** and search performance is critical (consider adding a `pg_trgm` GIN index or delegating to a search engine).
- You need **fuzzy matching** or typo tolerance (use Meilisearch or Algolia).

---

Requirements
------------

[](#requirements)

- PHP **8.3** or higher
- Laravel **12.x**
- PostgreSQL or MySQL (SQLite supported for testing)

---

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

[](#installation)

```
composer require maestrodimateo/laravel-search
```

The service provider is automatically discovered by Laravel.

---

Setup
-----

[](#setup)

### 1. Implement the `Searchable` contract

[](#1-implement-the-searchable-contract)

Add the `WithSearch` trait to your model and implement the `Searchable` interface to declare which columns are included in multi-column search.

```
use Illuminate\Database\Eloquent\Model;
use Maestrodimateo\Search\Contracts\Searchable;
use Maestrodimateo\Search\Traits\WithSearch;

class Article extends Model implements Searchable
{
    use WithSearch;

    protected $fillable = ['titre', 'auteur', 'meta'];

    protected $casts = ['meta' => 'array'];

    public function getFullTextColumns(): array
    {
        return ['titre', 'auteur', 'meta->ville'];
    }
}
```

> `Searchable` is only required for `fullTextSearch()`. The `search()` method works without it.

---

Usage
-----

[](#usage)

### Single-column search — `search()`

[](#single-column-search--search)

Performs a `LIKE` / `ILIKE` on **one column**.

```
// Search on a regular column
Article::search('titre', 'laravel')->get();

// Search on a JSON field
Article::search('meta->ville', 'paris')->get();
```

SQL generated (PostgreSQL):

```
SELECT * FROM articles WHERE titre ILIKE '%laravel%'
SELECT * FROM articles WHERE meta->>'ville' ILIKE '%paris%'
```

SQL generated (MySQL):

```
SELECT * FROM articles WHERE titre LIKE '%laravel%'
SELECT * FROM articles WHERE meta->>'$.ville' LIKE '%paris%'
```

---

### Multi-column search — `fullTextSearch()`

[](#multi-column-search--fulltextsearch)

Performs a `LIKE` / `ILIKE` across **all columns** declared in `getFullTextColumns()`.

```
Article::fullTextSearch('dupont')->get();
```

SQL generated (PostgreSQL):

```
SELECT * FROM articles
WHERE CONCAT_WS('-', titre, auteur, meta->>'ville') ILIKE '%dupont%'
```

SQL generated (MySQL):

```
SELECT * FROM articles
WHERE CONCAT_WS('-', titre, auteur, meta->>'$.ville') LIKE '%dupont%'
```

Spaces in the search term are automatically converted to `%` for flexible matching:

```
Article::fullTextSearch('jean paris')->get();
// binding: %jean%paris%
```

---

### Chaining with other scopes

[](#chaining-with-other-scopes)

Both methods return a `Builder` and can be combined with any Eloquent scope:

```
Article::fullTextSearch('dupont')
    ->where('meta->ville', 'Paris')
    ->orderBy('created_at', 'desc')
    ->paginate(15);
```

---

JSON columns
------------

[](#json-columns)

The package automatically converts JSON paths to the correct SQL syntax for the current database driver.

### Declaration syntax

[](#declaration-syntax)

Use `->` notation in `getFullTextColumns()` or in `search()`:

```
public function getFullTextColumns(): array
{
    return [
        'titre',          // regular column
        'auteur',         // regular column
        'meta->ville',    // JSON field
    ];
}
```

### Conversion per dialect

[](#conversion-per-dialect)

DeclarationPostgreSQLMySQL`titre``titre``titre``meta->ville``meta->>'ville'``meta->>'$.ville'``meta->addr->city``meta->'addr'->>'city'``meta->>'$.addr.city'`---

Supported dialects
------------------

[](#supported-dialects)

The package automatically detects the driver configured in `config/database.php`.

DriverOperatorJSON extraction`pgsql``ILIKE``->>` / `->'...'->>``mysql` / others`LIKE``->>'$.path'`---

`Searchable` contract
---------------------

[](#searchable-contract)

```
namespace Maestrodimateo\Search\Contracts;

interface Searchable
{
    /**
     * Columns used for multi-column full text search.
     * Supports JSON path notation with -> (e.g. "meta->ville").
     *
     * @return array
     */
    public function getFullTextColumns(): array;
}
```

If `fullTextSearch()` is called on a model that does not implement `Searchable`, a `LogicException` is thrown:

```
Maestrodimateo\Search\Tests\Models\ArticleWithoutSearchable must implement
Maestrodimateo\Search\Contracts\Searchable to use fullTextSearch.

```

---

Testing
-------

[](#testing)

The package tests use [Pest](https://pestphp.com) and [Orchestra Testbench](https://github.com/orchestral/testbench) with an in-memory SQLite database.

```
cd packages/maestrodimateo/laravel-search
./vendor/bin/pest --compact
```

---

Method reference
----------------

[](#method-reference)

### `search(string $attribute, ?string $search): Builder`

[](#searchstring-attribute-string-search-builder)

ParameterTypeDescription`$attribute``string`Column or JSON path (`column->key`)`$search``?string`Search term---

### `fullTextSearch(?string $search): Builder`

[](#fulltextsearchstring-search-builder)

ParameterTypeDescription`$search``?string`Search term — spaces are automatically converted to `%`> Requires the model to implement `Searchable`.

###  Health Score

41

—

FairBetter than 89% of packages

Maintenance89

Actively maintained with recent releases

Popularity7

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity51

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% 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

Unknown

Total

1

Last Release

54d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/92a2c64304e341345f2854b5bc9c43806b9e54f0b5b9b57135d37d69dd7c5c67?d=identicon)[mebalenoel](/maintainers/mebalenoel)

---

Top Contributors

[![maestrodimateo](https://avatars.githubusercontent.com/u/40523415?v=4)](https://github.com/maestrodimateo "maestrodimateo (1 commits)")

###  Code Quality

TestsPest

### Embed Badge

![Health badge](/badges/maestrodimateo-laravel-search/health.svg)

```
[![Health](https://phpackages.com/badges/maestrodimateo-laravel-search/health.svg)](https://phpackages.com/packages/maestrodimateo-laravel-search)
```

###  Alternatives

[barryvdh/laravel-ide-helper

Laravel IDE Helper, generates correct PHPDocs for all Facade classes, to improve auto-completion.

14.9k123.0M687](/packages/barryvdh-laravel-ide-helper)[fumeapp/modeltyper

Generate TypeScript interfaces from Laravel Models

196277.9k](/packages/fumeapp-modeltyper)[pressbooks/pressbooks

Pressbooks is an open source book publishing tool built on a WordPress multisite platform. Pressbooks outputs books in multiple formats, including PDF, EPUB, web, and a variety of XML flavours, using a theming/templating system, driven by CSS.

44643.1k1](/packages/pressbooks-pressbooks)[api-platform/laravel

API Platform support for Laravel

59126.4k6](/packages/api-platform-laravel)[dragon-code/migrate-db

Easy data transfer from one database to another

15717.4k](/packages/dragon-code-migrate-db)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

255.2k](/packages/aedart-athenaeum)

PHPackages © 2026

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