Download the PHP package kalimulhaq/qubuilder without Composer
On this page you can find all versions of the php package kalimulhaq/qubuilder. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download kalimulhaq/qubuilder
More information about kalimulhaq/qubuilder
Files in kalimulhaq/qubuilder
Package qubuilder
Short Description A Laravel package that converts structured JSON filter arrays into Eloquent query builder chains — enabling dynamic filtering, sorting, pagination, and eager loading via API requests.
License MIT
Homepage https://github.com/kalimulhaq/qubuilder
Informations about the package qubuilder
Qubuilder
Qubuilder turns a structured filter payload into a fully-chained Eloquent query — no manual if chains, no hand-rolled request parsers.
Send filters from an HTTP request (GET or POST) or pass them as a plain PHP array and get back a ready-to-paginate Builder in a single call. Every parameter is optional; use only what each endpoint needs.
Capabilities at a glance:
| Key | What it does |
|---|---|
select |
Choose which columns to return |
filter |
Nested AND/OR conditions with 20+ operators |
include |
Eager-load relations with sub-filters, sorts, and aggregates |
sort |
Multi-column ordering, including raw expressions |
group |
GROUP BY clauses |
page / limit |
Pagination with a configurable hard cap |
Requires: PHP 8.3+ · Laravel 11+
Installation
The service provider and facade are auto-discovered by Laravel.
Publish Config
Configuration
config/qubuilder.php
Limit clamping: Any
limitvalue abovemaxis silently clamped tomax. Values of0or below are also clamped tomax(not to1or the default), so sendinglimit=0returnsmaxrecords.
allow_select_all(defaulttrue): leave enabled to keep the current behaviour where an omittedselectreturns all columns. Set tofalseto force clients to request explicit columns —selectbecomes required at the top level and inside every non-aggregate include, the"*"wildcard is rejected by validation, and if a query still reaches the builder without columns it selects the model's primary key only. Aggregate includes (count,avg,sum,min,max) are exempt since they select no columns.
allow_include(defaulttrue): leave enabled to allow relation eager-loading. Set tofalseto disable includes entirely — theincludeparameter is silently stripped from the request (no validation error) and the builder never loads relations, even nested ones.
Quick Start
From a Plain Array
From an Existing Builder
Pass any Builder or Relation instance instead of a model class string to apply filters on top of an existing query.
From an HTTP Request
Both GET (query string) and POST (request body) are supported — the package reads from $request->input(), which transparently handles both methods.
You can also extend the built-in GetCollectionRequest to get automatic validation:
Detailed Example
A single filters payload that exercises every available option — shown as both a PHP array and its JSON equivalent for use in HTTP requests.
PHP Array
JSON (for HTTP requests — GET or POST)
The same payload encoded as JSON query-string parameters (GET) or request body (POST):
GET request tip: JSON-encode each parameter value individually in the query string — do not encode the whole object as one string.
Generated SQL
The payload above produces the following queries.
deleted_atappears in the filter, so->withTrashed()is applied — the automatic soft-delete scope (AND users.deleted_at IS NULL) is removed and the explicit condition from the filter takes its place.
Main query (aggregate include items are injected as SELECT subqueries):
Eager-load queries (non-aggregate include items run as separate queries):
API Reference
Static Constructors
| Method | Description |
|---|---|
Qubuilder::make($filters, $model) |
Create from array + model class or builder |
Qubuilder::makeFromArray(array $array, $model) |
Alias for make() |
Qubuilder::makeFromRequest(?Request $req, $model) |
Parse filters from the HTTP request |
Instance Methods
| Method | Returns | Description |
|---|---|---|
->filters(array) |
$this |
Set the filters array |
->model($model) |
$this |
Set the model or builder |
->query() |
Builder |
Build and return the Eloquent query |
->select() |
Select |
The resolved Select object |
->where() |
Where |
The resolved Where object |
->include() |
Includes |
The resolved Includes object |
->sort() |
Sorts |
The resolved Sorts object |
->page() |
int |
Resolved page number |
->limit() |
int |
Resolved per-page limit |
Filters Array Structure
Select
Generates ->select(['id', 'name', 'email']). Omitting select defaults to ['*'].
Filter (WHERE Conditions)
Each condition is an associative array with field, op, and optionally value.
Simple Condition
Conditions must always be wrapped in an array or an AND/OR group — a bare associative condition at the top level is not valid.
AND / OR Groups
Groups can be nested to any depth:
Filter Operators
Comparison
op |
SQL | Note |
|---|---|---|
= |
= value |
Default — used when op is omitted |
!= |
!= value |
Not-equal; standard SQL syntax |
<> |
<> value |
Not-equal; ISO SQL alias for != |
> |
> value |
Greater than |
< |
< value |
Less than |
>= |
>= value |
Greater than or equal to |
<= |
<= value |
Less than or equal to |
List
op |
SQL |
|---|---|
in |
WHERE field IN (...) |
not_in |
WHERE field NOT IN (...) |
between |
WHERE field BETWEEN a AND b |
not_between |
WHERE field NOT BETWEEN a AND b |
Null Checks
op |
SQL | value needed |
|---|---|---|
null |
IS NULL |
No |
not_null |
IS NOT NULL |
No |
Soft Deletes: Any filter condition targeting
deleted_at— regardless of operator — automatically applies->withTrashed()globally, so soft-deleted records are included in the result set. This means operators like=,between, ornot_nullondeleted_atall trigger the same behaviour.
Text Search (LIKE)
op |
Pattern | Matches |
|---|---|---|
_like |
%value |
ends with |
like_ |
value% |
starts with |
_like_ |
%value% |
contains |
Date & Time
Each operator extracts the specified component and compares with =.
op |
Eloquent method | Example value |
|---|---|---|
date |
whereDate |
'2025-06-15' |
year |
whereYear |
2025 |
month |
whereMonth |
6 |
day |
whereDay |
15 |
time |
whereTime |
'14:30:00' |
JSON Columns
op |
Eloquent method |
|---|---|
json_contains |
whereJsonContains |
json_not_contains |
whereJsonDoesntContain |
Use -> or dot notation to target a nested key.
Column Comparison
Compare two columns using field|<operator> syntax. Supported operators: =, !=, <>, >, <, >=, <=.
Raw WHERE
field is the raw SQL expression; value is the bindings array.
Relationship Existence — has / doesnthave
With count comparison (uses has / orHas):
Omitting the sub-operator defaults to =:
With sub-filters (uses whereHas):
Does not have:
Multi-Column — any / all / none
field accepts an array of columns. Append the per-column operator with |.
op |
Eloquent method |
|---|---|
any\|op |
whereAny |
all\|op |
whereAll |
none\|op |
whereNone |
Sort
Key-value pairs of column => direction. Multiple entries are applied in order.
Direction is validated — any value other than asc or desc defaults to asc.
Raw Sort Expression
Prefix the column key with raw: to use orderByRaw. The resolved direction is appended.
Group By
Array of column names passed to ->groupBy().
Rule: every column in
selectmust either appear ingroupor be an aggregate expression. If a column is ingroupbut not inselect, it won't appear in the result set — SQL will still accept it, but it is usually a mistake.
Generated SQL:
Combined with aggregate includes the sub-query columns are independent of the main select/group, so you can mix freely:
Generated SQL:
Include (Eager Loading)
Each include item is an array with a required name key (the Eloquent relation method name) and optional sub-filter keys.
Basic
With Sub-filters
All top-level filter keys (select, group, filter, include, sort, page, limit) work inside include items to scope the loaded relationship.
Nested Includes
Aggregate Includes
Set aggregate to compute a value instead of loading records. For avg, sum, min, max you must also set field.
aggregate |
Result attribute | field |
|---|---|---|
count |
{relation}_count |
Not required |
avg |
{relation}_avg_{field} |
Required |
sum |
{relation}_sum_{field} |
Required |
min |
{relation}_min_{field} |
Required |
max |
{relation}_max_{field} |
Required |
Aggregate includes also accept a filter key to scope the aggregation:
Polymorphic Relations (MorphTo)
If the relation is a MorphTo and the model defines a public {relation}Map() method, the package uses morphWith() to apply selective sub-includes per morph type.
The map keys are morph types — either the alias registered via Relation::morphMap() (e.g. 'post') or the model's fully-qualified class name (e.g. Post::class) when no morph map is configured. The values list the relations that may be eager-loaded for that type.
HTTP Request Integration
Form Request Classes
The package ships two ready-to-use FormRequest classes that validate every Qubuilder
query parameter before it reaches your controller. They can be used directly or extended
when you need to add your own authorisation logic, extra rules, or custom validation.
GetCollectionRequest
Validates all parameters for paginated list endpoints:
select, filter, include, sort, group (all JSON), page and limit (integers).
Use directly — type-hint it in your controller method:
Extend — add your own authorize(), extra rules, or override any method:
The built-in validation rules are available individually if you need to reuse them in a fully custom request class:
| Parameter | Rule class |
|---|---|
select, group |
ValidateStringArray |
filter |
ValidateFilter |
include |
ValidateInclude |
sort |
ValidateSort |
GetResourceRequest
Extends GetCollectionRequest but restricts validation to select and include only —
suitable for single-record endpoints where pagination, filtering, and sorting don't apply.
Use directly:
Extend — same pattern as GetCollectionRequest.
Both classes expose a ->filters() method that returns the normalised array, ready to
pass directly to Qubuilder::make().
Testing
Code Quality
Changelog
Please see CHANGELOG for recent changes.
Contributing
Please see CONTRIBUTING for details.
Security
If you discover a security issue please email [email protected] rather than using the public issue tracker.
Credits
- Kalim ul Haq
- Usman Ejaz
- Rana Usman Khan
- All Contributors
License
The MIT License (MIT). Please see License File for more information.
Support
If you find this package useful, consider supporting me on Ko-fi!
All versions of qubuilder with dependencies
illuminate/contracts Version ^11.0|^12.0|^13.0
illuminate/database Version ^11.0|^12.0|^13.0
illuminate/http Version ^11.0|^12.0|^13.0
illuminate/support Version ^11.0|^12.0|^13.0