NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages

Open source

Query Builder for Laravel

Install
composer require roundly-consulting/query-builder-for-laravel
Requires: PHP ^8.4 · Laravel ^12.0|^13.0

Overview

A native query builder for Laravel API list endpoints. Declare which filters and sorts an endpoint allows, and it reads the query string — filter[…], sort, page, per_page — applying only those and rejecting everything else with an HTTP 400. The result is still an Eloquent builder, so you keep chaining with(), get() or paginate(). MIT-licensed, with no runtime dependencies beyond Laravel, Symfony and two small companion Roundly packages.

What you get

Allow-list by default

Only declared filters and sorts run; anything else is an HTTP 400, or silently dropped in ignore mode.

Rich built-in filters

Exact, boolean, partial, prefix/suffix, comparison, scope, callback, trashed, JSON-array membership and custom filters.

Client-chosen operators

not:, contains: or gte: from a set you declare; an undeclared token stays a literal value.

Nullable & relation filters

A none sentinel, not:none, whereDoesntHave negations and value shapes that prevent PostgreSQL 500s.

Validated pagination

HasPageSize validates per_page (422) and hard-caps it; the configured page name is applied automatically.

Hardened by design

Bound values, escaped LIKE wildcards, request limits and length-capped error messages.

Documentation

Installation

Install via Composer, optionally publish the config and translations, and inspect the live wire contract with artisan about.

Configuration

Every config key and its default — parameter names, page-size bounds, unknown-parameter modes and request limits.

Building queries

Wrap a model or a prepared builder with QueryBuilder::for(), declare the allow-list, and keep chaining like any Eloquent builder.

Filters

Every built-in filter constructor — exact, boolean, partial, prefix/suffix, scope, callback, trashed and custom — plus value normalisation.

Operator filters

Fixed server-side comparisons with operator(), and client-chosen operators such as not:, contains: and gte: with operators().

Nullable, relation & JSON filters

Filter nullable columns with a none sentinel, to-many relations with whereDoesntHave negations, and JSON array columns by membership.

Value shapes

Declare a FilterValueShape on typed columns so a malformed uuid or id returns an empty result instead of a PostgreSQL 500.

Validating filter values

Wrap your validation rules in FilterValue so operator prefixes and sentinels are stripped before the rules run.

Sorting

Allow-list sort fields, map public names to columns, sort by several columns and set a default order.

Pagination

Validate and hard-cap per_page with the HasPageSize FormRequest trait; the configured page name is applied automatically.

Wire contract

The frozen query-string syntax for filters, operators, sorts and pagination, and the status code each mistake returns.

Unknown parameters & errors

Un-allow-listed filters and sorts return HTTP 400 with a translatable, length-capped message — or are dropped in ignore mode.

Custom filters & sorts

Implement the Filter or Sort contract for bespoke logic, and parse the operator wire in callbacks with RequestedOperator::split().

Security model

How the package keeps request input away from SQL: allow-lists, bound values, escaped wildcards, request limits and capped error output.

Testing

Drive the builder with Request::create() in unit tests, and assert 400 and 422 responses on your endpoints.

Requirements

PHP 8.4+, Laravel 12 or 13, and two companion packages installed automatically — no migrations or extra PHP extensions.

Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

More ways to support, including crypto

By donating, you agree to our donation terms.

Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.