Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Qubuilder Laravel Package

kalimulhaq/qubuilder

A Laravel package that simplifies constructing complex database queries. It provides a fluent, reusable API for dynamic filtering, sorting, and searching of Eloquent models, reducing boilerplate while keeping query logic readable and maintainable.

View on GitHub
Deep Wiki
Context7

Getting Started

qubuilder is a small, focused package, so onboarding is mostly about reading source rather than docs.

  1. Install and pin: composer require kalimulhaq/qubuilder:^1.3. v1.3.2 is a patch release published with only a changelog link, so there are no documented breaking changes — bumping from 1.3.1 is a low-risk composer update. Skim the compare diff anyway if you depend on edge-case filter behaviour, since patch releases in query-building packages often fix operator/parsing bugs that change generated SQL.
  2. Publish anything the package ships (php artisan vendor:publish --provider="Kalimulhaq\QuBuilder\QuBuilderServiceProvider") and immediately check whether that includes a config file. If it does, commit it — most of the package's behaviour (allowed operators, default page size, request key names) tends to be config-driven.
  3. Read in this order: README.md → config/qubuilder.php (if present) → src/ (the entry class is usually the thing you inject or extend).
  4. First use case: take an existing index endpoint with hand-rolled $request->query('sort') / where chains and replace it with the package's builder. That is the highest-value swap and it gives you an immediate side-by-side to validate output with ->toSql() before you ship.

If the README is thin, write your own 10-line usage example into the repo's docs as you discover it — you will be the documentation for the next developer.

Implementation Patterns

One builder class per resource. Rather than calling the package inline from controllers, wrap it:

final class InvoiceQuery
{
    public function __construct(private Request $request) {}

    public function build(): Builder
    {
        return QuBuilder::for(Invoice::query())
            ->allowedFilters(['status', 'customer_id', 'created_at'])
            ->allowedSorts(['created_at', 'total'])
            ->allowedIncludes(['customer', 'lines'])
            ->fromRequest($this->request);
    }
}

The allow-lists are the whole point — they are your injection boundary. Never pass $request->all() into a filter/sort setter.

Controller shape. Keep the controller to three lines: build, paginate, return a resource collection. Let the package own parsing and the resource own serialisation.

Compose with scopes, don't fight them. Applied scopes (tenant isolation, soft-delete policy, visibility rules) should be attached before the builder runs, so package-generated wheres land on top of them. Attaching scopes afterwards risks the builder overwriting a constraint if it uses the same column.

Whitelist at the boundary, transform inside. Validate request parameters with a FormRequest (types, enum membership, date formats) and let the builder handle structure. Doing both in the builder makes failures hard to attribute.

Testing. Assert on ->toSql() and bindings for filter/operator coverage, and assert HTTP-level behaviour (status, pagination meta, shape) for the endpoint. Query-assertion tests catch operator regressions on patch upgrades far faster than integration tests.

Reusable filter sets. If several resources share status / created_at / search, extract an allowedFilters() array into a shared trait or config so behaviour is consistent across endpoints.

Gotchas and Tips

  • Column names are the injection surface. Sort and filter parameters reaching ORDER BY / column positions without an allow-list are the classic failure mode for this class of package. Verify what happens with a bogus sort key before you trust it — the desired answer is "ignored" or "422", not "SQL error".
  • Silent no-ops. Many builders silently drop unknown filters rather than erroring. That's friendly in production and infuriating in development. Add a debug flag (or assert in tests) that fails loudly on unrecognised keys while you're building the endpoint.
  • includes and N+1. Eager loading via a request parameter is convenient and easy to abuse: a client can request a deep relation set on a large page. Cap allowed includes, consider ->limit() on nested relations, and check the query log with the largest page size your API permits.
  • Pagination drift. If the package sets a default page size from config, config caching (php artisan config:cache) will freeze that value — a very common "why did staging change?" moment. Confirm defaults explicitly in your own config rather than relying on the package's.
  • Patch-upgrade verification. v1.3.2 ships without itemised notes. After bumping, run the query-assertion tests and diff toSql() output on two or three representative requests against a pre-upgrade capture. If the generated SQL is byte-identical, you're done.
  • Extension points. If you need a custom operator or filter type, prefer registering it through the package's config/service-provider hook over subclassing internals — subclassing couples you to method signatures that patch releases can change without notice.
  • Escape hatch. Keep a documented way to bypass the builder (just build the query manually) for the one gnarly report endpoint that never fits the abstraction. Fighting a generic query builder is more expensive than one hand-written query.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin