PHPackages                             philiprehberger/laravel-search-query-parser - 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. philiprehberger/laravel-search-query-parser

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

philiprehberger/laravel-search-query-parser
===========================================

Parse GitHub-style search queries into structured filters for Laravel Eloquent. Supports field:value, comparisons, exclusions, and relation filters.

v1.1.4(1mo ago)116[1 PRs](https://github.com/philiprehberger/laravel-search-query-parser/pulls)MITPHPPHP ^8.2CI passing

Since Mar 6Pushed 1mo agoCompare

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

READMEChangelogDependencies (7)Versions (7)Used By (0)

Laravel Search Query Parser
===========================

[](#laravel-search-query-parser)

[![Tests](https://github.com/philiprehberger/laravel-search-query-parser/actions/workflows/tests.yml/badge.svg)](https://github.com/philiprehberger/laravel-search-query-parser/actions/workflows/tests.yml)[![Latest Version on Packagist](https://camo.githubusercontent.com/182ba38410245425016d5583488dec3ddaba4a00c2e7be5b8984517124a7f129/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7068696c69707265686265726765722f6c61726176656c2d7365617263682d71756572792d7061727365722e737667)](https://packagist.org/packages/philiprehberger/laravel-search-query-parser)[![License](https://camo.githubusercontent.com/7b5aa28d4c0ebd55858f2922bb9d16b4a25df6bcb481246ddb3f4ef016d656cd/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f7068696c69707265686265726765722f6c61726176656c2d7365617263682d71756572792d706172736572)](LICENSE)

Parse GitHub-style search queries into structured filters for Laravel Eloquent. Supports field:value, comparisons, exclusions, and relation filters.

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

[](#requirements)

- PHP 8.2+
- Laravel 11 or 12

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

[](#installation)

```
composer require philiprehberger/laravel-search-query-parser
```

The service provider is registered automatically via Laravel's package auto-discovery.

Quick Start
-----------

[](#quick-start)

```
use PhilipRehberger\SearchQueryParser\QueryParser;

$parser = new QueryParser();
$parsed = $parser->parse('design status:active amount:>1000 -archived');

$parsed->textSearch;    // "design"
$parsed->filters;       // [['field' => 'status', 'operator' => 'equals', 'value' => 'active'], ...]
$parsed->excludeTerms;  // ["archived"]

$parsed->hasTextSearch();    // true
$parsed->hasFilters();       // true
$parsed->hasExcludeTerms();  // true
$parsed->isEmpty();          // false
```

You can also resolve `QueryParser` from the container or use the facade:

```
// Via facade
use PhilipRehberger\SearchQueryParser\Facades\SearchQueryParser;

$parsed = SearchQueryParser::parse('status:active');

// Via dependency injection
public function __construct(private QueryParser $parser) {}
```

Syntax Reference
----------------

[](#syntax-reference)

SyntaxExampleDescription`keyword``design`Plain keyword — goes into `textSearch``"phrase"``"web design"`Quoted phrase — treated as a single text search term`field:value``status:active`Exact match filter (`equals` operator)`field:>value``amount:>1000`Greater than comparison`field:=500`Greater than or equal`field: x, 'max' => y]` or `[x, y]`.

### Date Operators

[](#date-operators)

ClassLabelInput TypeRequires Value`DateEqualsOperator`on datedateyes`DateBeforeOperator`beforedateyes`DateAfterOperator`afterdateyes`DateBetweenOperator`between datesdaterangeyes`DateInLastOperator`in the lastdurationyes`DateInNextOperator`in the nextdurationyes`IsTodayOperator`is todaytextno`IsThisWeekOperator`is this weektextno`IsThisMonthOperator`is this monthtextno`DateInLastOperator` and `DateInNextOperator` accept `['amount' => int, 'unit' => 'days|weeks|months|years']`.

`DateBetweenOperator` accepts `['start' => date, 'end' => date]` or `[date, date]`.

### Array Operators (JSON columns)

[](#array-operators-json-columns)

ClassLabelInput Type`InOperator`is any ofmultiselect`NotInOperator`is not any ofmultiselect`HasAnyOperator`has any ofmultiselect`HasAllOperator`has all ofmultiselect`HasAnyOperator` and `HasAllOperator` use `whereJsonContains` for JSON array columns.

### Relation Operators

[](#relation-operators)

ClassLabelRequires Value`HasRelationOperator`hasno`HasNotRelationOperator`does not haveno`HasCountOperator`has countyes`HasCountOperator` accepts `['operator' => '>=', 'count' => 1]`.

Usage with Eloquent
-------------------

[](#usage-with-eloquent)

The `ParsedQuery` DTO gives you structured data you can apply to your queries however you like. Here is a typical pattern:

```
use PhilipRehberger\SearchQueryParser\QueryParser;
use PhilipRehberger\SearchQueryParser\Operators\Text\ContainsOperator;
use PhilipRehberger\SearchQueryParser\Operators\Text\EqualsOperator;
use PhilipRehberger\SearchQueryParser\Operators\Numeric\GreaterThanOperator;
use PhilipRehberger\SearchQueryParser\Operators\Array\InOperator;
use PhilipRehberger\SearchQueryParser\Operators\Relation\HasRelationOperator;
use PhilipRehberger\SearchQueryParser\Operators\Relation\HasNotRelationOperator;

$parser = new QueryParser();
$parsed = $parser->parse($request->input('q', ''));

$query = Project::query();

// Apply free-text search
if ($parsed->hasTextSearch()) {
    $term = $parsed->textSearch;
    $query->where(function ($q) use ($term) {
        $q->where('name', 'like', "%{$term}%")
          ->orWhere('description', 'like', "%{$term}%");
    });
}

// Apply field filters
$operatorMap = [
    'equals'        => new EqualsOperator(),
    'in'            => new InOperator(),
    'greater_than'  => new GreaterThanOperator(),
    'has'           => new HasRelationOperator(),
    'has_not'       => new HasNotRelationOperator(),
];

foreach ($parsed->filters as $filter) {
    $operator = $operatorMap[$filter['operator']] ?? null;
    if ($operator) {
        $operator->apply($query, $filter['field'], $filter['value']);
    }
}

// Apply exclusion terms
foreach ($parsed->excludeTerms as $term) {
    $query->where('name', 'not like', "%{$term}%");
}

$projects = $query->get();
```

Build / Round-trip
------------------

[](#build--round-trip)

`QueryParser::build()` serializes a `ParsedQuery` back into a query string. This is useful for storing canonical search state or passing queries between requests.

```
$parsed = $parser->parse('design status:active -archived');

// Modify the parsed query...
$built = $parser->build($parsed);
// "design status:active -archived"
```

Syntax Help
-----------

[](#syntax-help)

`getSyntaxHelp()` returns all supported syntax patterns, suitable for rendering a help tooltip or autocomplete:

```
$help = $parser->getSyntaxHelp();
// [
//   ['syntax' => 'keyword',       'example' => 'design',           'description' => 'Search for keyword in all fields'],
//   ['syntax' => '"phrase"',      'example' => '"web design"',     'description' => 'Search for exact phrase'],
//   ['syntax' => 'field:value',   'example' => 'status:active',    'description' => 'Filter by specific field'],
//   ...
// ]
```

ParsedQuery DTO
---------------

[](#parsedquery-dto)

```
readonly class ParsedQuery
{
    public string $textSearch;
    public array  $filters;      // array
    public array  $excludeTerms; // array

    public function hasTextSearch(): bool;
    public function hasFilters(): bool;
    public function hasExcludeTerms(): bool;
    public function isEmpty(): bool;
    public function toArray(): array;
}
```

API
---

[](#api)

### `QueryParser`

[](#queryparser)

MethodDescription`parse(string $query): ParsedQuery`Parse a query string into a structured `ParsedQuery` DTO`build(ParsedQuery $parsed): string`Serialize a `ParsedQuery` back into a query string`getSyntaxHelp(): array`Return all supported syntax patterns for tooltips or autocomplete### `ParsedQuery` DTO

[](#parsedquery-dto-1)

Property / MethodTypeDescription`$textSearch``string`Free-text portion of the query`$filters``array`Structured filters: `[{field, operator, value}]``$excludeTerms``array`Terms prefixed with `-``hasTextSearch(): bool`—Whether a free-text term is present`hasFilters(): bool`—Whether any field filters are present`hasExcludeTerms(): bool`—Whether any exclusion terms are present`isEmpty(): bool`—Whether the query produced no results`toArray(): array`—Serialize to arrayDevelopment
-----------

[](#development)

```
composer install
vendor/bin/phpunit
vendor/bin/pint --test
vendor/bin/phpstan analyse
```

License
-------

[](#license)

MIT

###  Health Score

41

—

FairBetter than 89% of packages

Maintenance89

Actively maintained with recent releases

Popularity10

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity50

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

Every ~2 days

Total

6

Last Release

56d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/cfd7d24cbbf32400fa13ce0bbe7a31edd2d66a6d4488eafdb3d64c5337bf0435?d=identicon)[philiprehberger](/maintainers/philiprehberger)

---

Top Contributors

[![philiprehberger](https://avatars.githubusercontent.com/u/8218077?v=4)](https://github.com/philiprehberger "philiprehberger (11 commits)")

---

Tags

searchlaravelparsereloquentqueryfilter

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/philiprehberger-laravel-search-query-parser/health.svg)

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

###  Alternatives

[tucker-eric/eloquentfilter

An Eloquent way to filter Eloquent Models

1.8k4.8M26](/packages/tucker-eric-eloquentfilter)[mehdi-fathi/eloquent-filter

Eloquent Filter adds custom filters automatically to your Eloquent Models in Laravel.It's easy to use and fully dynamic, just with sending the Query Strings to it.

450191.6k1](/packages/mehdi-fathi-eloquent-filter)[mohammad-fouladgar/eloquent-builder

527189.5k](/packages/mohammad-fouladgar-eloquent-builder)[reedware/laravel-relation-joins

Adds the ability to join on a relationship by name.

2121.2M13](/packages/reedware-laravel-relation-joins)[aldemeery/sieve

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

1396.3k](/packages/aldemeery-sieve)[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)
