PHPackages                             nycu-csit/laravel-query-builder - 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. nycu-csit/laravel-query-builder

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

nycu-csit/laravel-query-builder
===============================

Build query by query string

v1.0.0(5mo ago)0175MITPHPPHP &gt;=8.2

Since May 10Pushed 5mo agoCompare

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

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

Laravel Query Builder
=====================

[](#laravel-query-builder)

This package makes you to filter, sort, include, count eloquent model easily based on the query string from the request.

QueryBuilder
------------

[](#querybuilder)

`NycuCsit\LaravelQueryBuilder\QueryBuilder` extends laravel query builder and supports fluent interface, you can use any laravel query builder function call on it.

```
use NycuCsit\LaravelQueryBuilder\QueryBuilder;
use NycuCsit\LaravelQueryBuilder\OperatorSet;

QueryBuilder::for(User::class)
    ->whereNull('deleted_at')   // laravel query builder function
    ->allowedFilter('year', 'number', OperatorSet::NUMBER_NULLABLE)   // filter feature
    ->get();   // laravel query builder function
```

Filtering
---------

[](#filtering)

The `filter` query parameters can be used to add where clauses to your Eloquent query. Only allowed query parameters could be parsed and built as a SQL query. If the query parameters is not allowed, it will be **skipped** without any error.

The supported format of query string:

- `filter[][]=` is JSON:API format, this format is **strongly recommended**.
- `filter[]=` is JSON:API format
- `[]=` is seen as a filter
- `=` is seen as a filter

Use `QueryBuilder` to parse query string and build query:

```
QueryBuilder::for(User::class)
    ->allowedFilter(
        'year',                         // parameter name
        'number',                       // type
        OperatorSet::NUMBER_NULLABLE,   // allowed operators
        'registered_year',              // column name, if omitted, use parameter name as column name
        'eq',                           // default operator, 'eq' if omitted
    )
    ->toSql();
```

The SQL query of `GET /users?year[gt]=2022` will be look like this:

```
select * from `users` where `registered_year` > 2022
```

Add many allowed query parameter filters:

```
QueryBuilder::for(User::class)
    ->allowedFilterMany(
        ['year', 'number', OperatorSet::NUMBER_NULLABLE, 'registered_year', 'eq'],
        ['email', 'string', OperatorSet::STRING],
        // ...
    )
    ->toSql();
```

Use `add()` to add allowed query parameter filter:

```
use NycuCsit\LaravelQueryBuilder\Criteria\AllowedFilter;

QueryBuilder::for(User::class)
    // use add() to add any implementation of NycuCsit\Contract\CriteriaQueryBuilder
    // shorthand criteria are in NycuCsit\Criteria
    ->add([
        AllowedFilter::for('email', 'string', OperatorSet::STRING, 'other_email', 'eq')
    ])
    ->toSql();
```

### Operators

[](#operators)

OperatorMeaningValueStringNumberBooleanDatetimeDateTime`eq`Equals toAny✅✅✅✅✅✅`neq`Not equals toAny✅✅✅✅✅✅`gt`Greater thanAny✅✅✅✅✅✅`lt`Less thenAny✅✅✅✅✅✅`ge`Greater or equals toAny✅✅✅✅✅✅`le`Less or equals toAny✅✅✅✅✅✅`in`Equals to one of arrayComma-seperated value✅✅✅✅✅✅`notin`Not equals to one of arrayComma-seperated value✅✅✅✅✅✅`is`Is`null` or `notnull`✅✅✅✅✅✅`like`Like (SQL fuzzy string)string✅❌❌❌❌❌`year_eq`Year equals tonumber❌❌❌✅✅✅`month_eq`Month equals tonumber❌❌❌✅✅✅`day_eq`Day equals tonumber❌❌❌✅✅✅`date_eq`Date equals todate string (RFC3339)❌❌❌✅✅✅`time_eq`Date equals totime string (RFC3339)❌❌❌✅✅✅If there aren't a specified `[operator]` , the query builder will use the default operator you specified. By default, the operator is `eq`.

### Query Scope

[](#query-scope)

The `scope` query parameters can be used to apply a [Query Scope](https://laravel.com/docs/master/eloquent#query-scopes) to your Eloquent query. Only allowed scope could be parsed and built as a SQL query. If the scope is not allowed, it will be **skipped** without any error.

Supports these format of query string:

- `scope[]=`
    - Toggle the scope
    - `` is the name of your scope, it is camelCase format
    - `` boolean value, specify whether to apply this scope
- `scope[][]=`
    - For [dynamic scope](https://laravel.com/docs/master/eloquent#dynamic-scopes)
    - `` is the name of your scope, it is camelCase format
    - `` is the argument name to be passed to the scope
    - `` is the argument value to be passed to the scope

For example, you may define a scope function:

```
// The name of this scope is 'banned'
public function scopeBanned($query)
{
    return $query->where('banned', true);
}
```

Use `allowedScopes()` in the query builder:

```
QueryBuilder::for(\App\Models\User::class)
    ->allowedScopes(
        [
            'isBanned',   // parameter name
            null,         // argument transformer
            'banned'      // scope name, null if the parameter name is scope name
        ], // other scopes ...
    )
    ->toSql();
```

The query string

```
?scope[isBanned]=1

```

will be applied as `$query->banned()`.

The arguments will be passed by corresponding names, the order does not affect. If the arguments doesn't fit the scope function's definition, this scope query string will be ignored.

#### Argument Transformer

[](#argument-transformer)

You may check or modify the arguments array in the transformer. The transformer could be an array of callables or single callable, the array transformer will be invoked one by one.

The scope query builder will send the arguments in the query string of the scope to the transformers.

```
// The name of this scope is 'ofCondition'
public function scopeOfCondition($query, string $email = '', int $id = -1, bool $active = true)
{
    return $query->where('email', $email)->orWhere('id', $id)->orWhere('active', $active);
}
```

Here is the query string:

```
?scope[ofCondition][email]=admin@test.com&scope[ofCondition][id]=946&scope[ofCondition][active]=true

```

the arguments of scope 'ofCondition' is:

```
[
    'email' => 'admin@test.com',
    'id' => '946',
    'active' => 'true'
]
```

You may use [Cast](src/Builders/Cast.php) as transformer to cast string to other type in the arguments:

```
use NycuCsit\LaravelQueryBuilder\Builders\Cast;

QueryBuilder::for(\App\Models\User::class)
    ->allowedScopes(
        [
            'ofCondition',   // parameter name, also scope name
            [Cast::byKey('id', 'number'), Cast::byKey('active', 'bool')],   // argument transformer
        ], // other scopes ...
    )
    ->toSql();
```

Or, you can just use a closure as transformer:

```
function ($args) {
    $args['id'] = intval($args['id']);
}
```

Filtering Existence
-------------------

[](#filtering-existence)

The `filter` query parameters with existence operators can be used to add [has()](https://laravel.com/docs/9.x/eloquent-relationships#querying-relationship-existence) clauses to your Eloquent query. The not allowed query parameters will be **skipped** without any error.

The supported format of query string:

- `filter[][]=` is JSON:API format

Use `QueryBuilder` to parse query string and build query:

```
QueryBuilder::for(User::class)
    ->allowedFilterExistence([
        'posts',                    // parameter name
        'news_posts',               // relationship name
        OperatorSet::EXIST_COUNT    // allowed operators, OperatorSet::EXIST if omitted
    ])
    ->toSql();
```

The SQL query of `GET /users?filter[posts][exist]=true` will be look like this:

```
select * from `users` where exists (select * from `news_posts` where `users`.`id` = `news_posts`.`user_id`)
```

Add many allowed query parameter existence filters:

```
QueryBuilder::for(User::class)
    ->allowedFilterExistenceMany(
        ['posts', 'posts', OperatorSet::EXIST_COUNT],
        ['orders']
        // ...
    )
    ->toSql();
```

Use `add()` to add allowed query parameter existence filter:

```
use NycuCsit\LaravelQueryBuilder\Criteria\AllowedFilterExistence;

QueryBuilder::for(User::class)
    ->add([
        AllowedFilterExistence::for('orders', 'orders', OperatorSet::EXIST_COUNT)
    ])
    ->toSql();
```

### Operators

[](#operators-1)

OperatorMeaningValue`exist`Have at least one related recordbool`exist_eq`Number of related records equals tonumber`exist_neq`Number of related records not equals tonumber`exist_gt`Number of related records greater thannumber`exist_lt`Number of related records less thennumber`exist_ge`Number of related records greater or equals tonumber`exist_le`Number of related records less or equals tonumberIncluding relationships
-----------------------

[](#including-relationships)

The `include` query parameter will load any Eloquent relation or relation count on the resulting models. All includes must be explicitly allowed using allowedIncludes().

The supported format of query string:

- `include=,,...` is JSON:API format
- `[include]=` &lt;value&gt; is boolean

Use `QueryBuilder` to parse query string and build query:

```
QueryBuilder::for(User::class)
    ->allowedIncludes([
        // key is parameter name, if there are no string key, use relationship name as parameter name
        // value is relationship name
        'posts' => 'news_posts',
        'orders'
        // ...
   ])
    ->toSql();
```

The SQL query of `GET /users?include=posts` will be look like this:

```
select * from `users`
select * from `news_posts` where `news_posts`.`user_id` in (...)
```

Be caution, you should call `allowedIncludes` or `add(AllowedIncludes...)` only once per query, because including validation will be added in future version.

The corresponding shorthand for `add()` is `NycuCsit\LaravelQueryBuilder\Criteria\AllowedIncludes`.

Sorting
-------

[](#sorting)

The `sort` query parameter is used to determine by which property the results' collection will be ordered. Sorting is ascending by default and can be reversed by adding a hyphen (-) to the start of the property name.

If there is any not allowed parameter in `sort` query parameter, an Illuminate\\Validation\\ValidationException will be thrown.

The supported format of query string:

- `sort=,,...` is JSON:API format

Use `QueryBuilder` to parse query string and build query:

```
QueryBuilder::for(User::class)
    ->allowedSorts([
        // key is parameter name, if there are no string key, use column name as parameter name
        // value is column name
        'create_time' => 'created_at',
        'email'
        // ...
   ])
    ->toSql();
```

The SQL query of `GET /users?sort=create_time,-email` will be look like this:

```
select * from `users` order by `created_at` asc, `email` desc
```

The corresponding shorthand for `add()` is `NycuCsit\LaravelQueryBuilder\Criteria\AllowedSorts`.

Counting relationship
---------------------

[](#counting-relationship)

The `count` query parameter will count on the related records. All counts must be explicitly allowed using allowedCounts().

The supported format of query string:

- `count=,,...` is JSON:API format
- `[count]=` &lt;value&gt; is boolean

Use `QueryBuilder` to parse query string and build query:

```
QueryBuilder::for(User::class)
    ->allowedCounts([
        // key is parameter name, if there are no string key, use relationship name as parameter name
        // value is relationship name
        'posts' => 'news_posts',
        'orders'
        // ...
   ])
    ->toSql();
```

The SQL query of `GET /users?count=posts` will be look like this:

```
select `users`.*, (select count(*) from `news_posts` where `users`.`id` = `news_posts`.`user_id`) as `news_posts_count` from `users`
```

As you can see, there is a new field `news_posts_count` is appended, but the field name will be`_count` instead of `_count`.

The corresponding shorthand for `add()` is `NycuCsit\LaravelQueryBuilder\Criteria\AllowedCounts`.

Extra Queries for single Model
------------------------------

[](#extra-queries-for-single-model)

### Eager Loading

[](#eager-loading)

Sometimes, we want to load relationships for a model by query string. Just use [HasExtraQuery](src/ModelCriteria/HasExtraQuery.php) trait in your model class:

```
use NycuCsit\LaravelQueryBuilder\ModelCriteria\HasExtraQuery;

class Post extends Model
{
    use HasExtraQuery;

    // ...
}
```

The supported format of query string:

- `load[]=` is JSON:API format
    - `` the name which you want to eager load
    - `` boolean value, toggle the eager loading

Now, you can use `allowedLoad()` function on your model:

```
$post = Post::find($id);
$post->allowedLoad(/* parameter name */'author', /* relation name */'user');
```

The query string `&load[author]=1` will be applied as `$post->load('user')`.

The `allowedLoad()` function supports fluent interface.

###  Health Score

42

—

FairBetter than 90% of packages

Maintenance69

Regular maintenance activity

Popularity15

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity64

Established project with proven stability

 Bus Factor1

Top contributor holds 87.5% 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 ~322 days

Total

5

Last Release

179d ago

Major Versions

v0.3.0 → v1.0.02025-11-18

PHP version history (2 changes)v0.1.0PHP &gt;=7.4

v1.0.0PHP &gt;=8.2

### Community

Maintainers

![](https://www.gravatar.com/avatar/6b52c3484e8cbef7ae4cd3112390f3c3c860046219663c531f42ae2990ac3f1f?d=identicon)[nycu-csit](/maintainers/nycu-csit)

---

Top Contributors

[![zhshize](https://avatars.githubusercontent.com/u/23548371?v=4)](https://github.com/zhshize "zhshize (7 commits)")[![CSY54](https://avatars.githubusercontent.com/u/18496305?v=4)](https://github.com/CSY54 "CSY54 (1 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/nycu-csit-laravel-query-builder/health.svg)

```
[![Health](https://phpackages.com/badges/nycu-csit-laravel-query-builder/health.svg)](https://phpackages.com/packages/nycu-csit-laravel-query-builder)
```

###  Alternatives

[anourvalar/eloquent-serialize

Laravel Query Builder (Eloquent) serialization

11320.2M21](/packages/anourvalar-eloquent-serialize)[overtrue/laravel-versionable

Make Laravel model versionable.

585308.0k5](/packages/overtrue-laravel-versionable)[abbasudo/laravel-purity

elegant way to add filter and sort in laravel

514330.5k1](/packages/abbasudo-laravel-purity)[statamic-rad-pack/runway

Eloquently manage your database models in Statamic.

135192.6k5](/packages/statamic-rad-pack-runway)[dragon-code/laravel-deploy-operations

Performing any actions during the deployment process

240173.5k2](/packages/dragon-code-laravel-deploy-operations)[stayallive/laravel-eloquent-observable

Register Eloquent model event listeners just-in-time directly from the model.

2928.9k7](/packages/stayallive-laravel-eloquent-observable)

PHPackages © 2026

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