PHPackages                             lgrevelink/laravel-custom-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. lgrevelink/laravel-custom-query-builder

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

lgrevelink/laravel-custom-query-builder
=======================================

Utility project for creating custom query builders in Laravel.

0.2.2(3y ago)026.6k↓47%1[1 PRs](https://github.com/LarsGrevelink/laravel-custom-query-builder/pulls)MITPHPPHP &gt;=7.1CI failing

Since May 19Pushed 4mo ago1 watchersCompare

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

READMEChangelog (2)Dependencies (4)Versions (5)Used By (0)

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

[](#laravel-custom-query-builder)

[![Test Suite Status](https://github.com/larsgrevelink/laravel-custom-query-builder/workflows/Test%20Suite/badge.svg)](https://github.com/larsgrevelink/laravel-custom-query-builder)[![Total Downloads](https://camo.githubusercontent.com/204474dcd72ca0f2491a4725caf47c1b8dde4ade8d6e1411b101e22279a68572/68747470733a2f2f706f7365722e707567782e6f72672f6c67726576656c696e6b2f6c61726176656c2d637573746f6d2d71756572792d6275696c6465722f642f746f74616c2e737667)](https://packagist.org/packages/lgrevelink/laravel-custom-query-builder)[![Latest Stable Version](https://camo.githubusercontent.com/5bfdaac3fcf91c01057d3e5901ab7ed933d003aa73b43948edeedf41d76a1574/68747470733a2f2f706f7365722e707567782e6f72672f6c67726576656c696e6b2f6c61726176656c2d637573746f6d2d71756572792d6275696c6465722f762f737461626c652e737667)](https://packagist.org/packages/lgrevelink/laravel-custom-query-builder)[![License](https://camo.githubusercontent.com/e8f1e76d646ddd1c01e013730390a6cbd95621f4a9c9fdc90d1e89b2e8002544/68747470733a2f2f706f7365722e707567782e6f72672f6c67726576656c696e6b2f6c61726176656c2d637573746f6d2d71756572792d6275696c6465722f6c6963656e73652e737667)](https://github.com/larsgrevelink/laravel-custom-query-builder)

A custom query builder which allows projects to use Eloquent's builder on an application level. Define joins, filters, sorting and scopes with proper IntelliSense through a thin abstraction layer.

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

[](#installation)

```
composer require lgrevelink/laravel-custom-query-builder
```

Configuration for Laravel
-------------------------

[](#configuration-for-laravel)

Laravel's auto-discovery directly registers the service provider so it should be instantly usable. If you don't use auto-discovery, please add the `ServiceProvider` to the provider array in `config/app.php`.

```
LGrevelink\CustomQueryBuilder\ServiceProvider::class
```

The artisan command is directly registered by adding the service provider. If you want to change the default configuration you can publish it through the following command;

```
php artisan vendor:publish --provider="LGrevelink\CustomQueryBuilder\ServiceProvider"
```

Configuration for Lumen
-----------------------

[](#configuration-for-lumen)

Using this package in lumen requires you to register the service provider in `bootstrap/app.php`.

```
$app->register(LGrevelink\CustomQueryBuilder\ServiceProvider::class);
```

The artisan command is directly registered by adding the service provider. If you want to change the default configuration you can publish it through the following command;

```
$app->configure('querybuilder');
```

Usage
-----

[](#usage)

Models use Eloquent's builder as a default when running operations from your model. This package allows you to override this default behaviour with a custom query builder which can be hosted in your project.

#### Create a new query builder (generator)

[](#create-a-new-query-builder-generator)

The package includes an artisan make command which configures an example builder at the given location. Simply run the following and you should have the builder;

```
php artisan make:query-builder MyQueryBuilder
```

#### Assigning a query builder

[](#assigning-a-query-builder)

After creating the query builder we need to assign it to the model. The model needs to have the `HasCustomQueryBuilder` concern applied to it. This can be done by extending the `LGrevelink\CustomQueryBuilder\Model` instead of the Eloquent's model or adding the trait directly to the class. This only initiates a connection to the `CustomQueryBuilder`. To use your own you have to set it in the model;

```
class SomeModel extends Model
{
    use LGrevelink\CustomQueryBuilder\Concerns\HasCustomQueryBuilder;

    protected $queryBuilder = App\QueryBuilders\MyQueryBuilder::class;
}
```

#### Using the query builder

[](#using-the-query-builder)

The default naming structures for filters and sorting are `filterOn%s` and `sortBy%s` where the placeholder will be replaced by a **singular or plural** version of the filter depending on the filter value. In case it's an array it attempts the plural version. Any other value will make use of the singular version. Below are some examples where each of the sets acts the same.

```
$builder = SomeModel::select();

// Using direct filters on the query builder
$builder->filterOnProperty(1234);
$builder->filterOnCategories([1, 2]);
$builder->sortByCategory('asc');
$builder->sortByTitle('asc');

// Enforcing the naming structure
$builder->applyFilter('property', 1234); // Calls filterOnProperty
$builder->applyFilter('category', [1, 2]); // Calls filterOnCategories
$builder->applySorting('category', 'asc'); // Calls sortByCategory
$builder->applySorting('title', 'asc'); // Calls sortByTitle

// Setting them in bulk
$builder->applyFilters([
    'property' => 1234,
    'category' => [1, 2],
); // Calls both filterOnProperty and filterOnCategories

$builder->applySorting([
    'category' => 'asc',
    'title' => 'asc',
]); // Calls both sortByCategory and sortByTitle
```

#### Global scopes directly from the builder

[](#global-scopes-directly-from-the-builder)

If you want to keep all database related data, including global scopes, in the query builder; you can! They are only added when the models dictate that they should be added but it keeps you from having to add these through the `Model->boot` functions.

```
class MyQueryBuilder extends CustomQueryBuilder
{
    protected $globalScopes = [
        MyScope::class,
    ];
}
```

#### Strict exceptions

[](#strict-exceptions)

In case a filter does not exist an exception will be thrown. There is a fallback for these cases which automatically applies a `where` or `whereIn` for unknown filters and applies an `orderBy` for unknown sortings. By default, the query builder's mode is set to `strict` and this behaviour is prevented. You can change this by overriding the `querybuilder.mode` config value and set it to `auto`. **Be aware that this could have side-effects if the input is not validated properly.**

Utilities
---------

[](#utilities)

#### joinOnce

[](#joinonce)

The `joinOnce` method can be used to join tables but prevent duplicates. It makes use of the `\Illuminate\Database\Query\Builder`'s `join` method does a basic table validation before adding the join to the query. This way multiple joins on the same table can be prevented.

```
class ProductQueryBuilder extends CustomQueryBuilder
{
    public function joinCategories() {
        return $this->joinOnce('categories', 'categories.id', 'products.category_id');
    }

    public function filterOnCategoryStatus(string $status) {
        return $this->joinCategories()->where('categories.status', $status);
    }

    public function filterOnCategoryTitle(string $title) {
        return $this->joinCategories()->where('categories.title', 'LIKE', $title);
    }
}
```

In this case when filtering on status as well as title the join will only be forged once instead of multiple times.

#### Wildcard column qualifying

[](#wildcard-column-qualifying)

Using unqualified wildcards in select statements can have side-effects which are hard to find. When using joins, values of the original table can be overwritten by the joined tables when the column naming is the same. To prevent this behaviour we qualify the unqualified wildcards. In case the overwriting is the behaviour you seek, we suggest to specifically add the columns you want to the select statement. Instead of making it a side effect, it should be a deliberate choice the developer is aware of.

###  Health Score

36

—

LowBetter than 82% of packages

Maintenance52

Moderate activity, may be stable

Popularity28

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity44

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 ~347 days

Total

4

Last Release

1147d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/8b94a0369dd7815f25856019b12c61d519816d84af15a34186bb3cb8c6bb65f5?d=identicon)[lgrevelink](/maintainers/lgrevelink)

---

Top Contributors

[![LarsGrevelink](https://avatars.githubusercontent.com/u/1597445?v=4)](https://github.com/LarsGrevelink "LarsGrevelink (22 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

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

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

###  Alternatives

[spatie/laravel-backup

A Laravel package to backup your application

6.0k21.8M191](/packages/spatie-laravel-backup)[tucker-eric/eloquentfilter

An Eloquent way to filter Eloquent Models

1.8k4.8M26](/packages/tucker-eric-eloquentfilter)[laravel-doctrine/orm

An integration library for Laravel and Doctrine ORM

8425.3M87](/packages/laravel-doctrine-orm)[ryangjchandler/orbit

A flat-file database driver for Eloquent.

922256.2k5](/packages/ryangjchandler-orbit)[clickbar/laravel-magellan

This package provides functionality for working with the postgis extension in Laravel.

423715.4k1](/packages/clickbar-laravel-magellan)[cybercog/laravel-clickhouse

ClickHouse migrations for Laravel

163166.8k](/packages/cybercog-laravel-clickhouse)

PHPackages © 2026

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