rapidez/statamic-query-builder
Brings Statamic content querying to Rapidez, adding a fluent query builder so you can fetch and filter CMS entries directly in your Laravel storefront using familiar, Eloquent-style syntax for flexible content-driven pages.
composer require and check whether the package ships a publishable config (php artisan vendor:publish). Read the config file first — it is almost always the map of what the package will and won't do for you.?sort[]=...). That one detail determines how your controllers and frontend will look.GET /posts index that sorts by created_at and title, backed by a model with no joins and no scopes.$request->sort ? orderBy(...) : ... logic in an index action with a whitelisted, declarative sort definition. That gives you validation, a default ordering, and protection against arbitrary column names in one move.composer.json before adopting, and pin the version. The 3.4.0 release only adds sortings, so it is a safe minor bump — but re-run your sort-related tests after upgrading in case a new sorting changes resolution order for ambiguous input.Whitelist, never trust the request. Keep the set of sortable columns in a dedicated class or config array rather than in the controller. Treat it as an allow-list: unknown columns should be rejected or ignored explicitly, not passed through to orderBy.
One definition, many endpoints. Put shared sorts (e.g. name, created_at, -created_at) into a reusable definition and compose per-endpoint variants for the extra, resource-specific fields. This keeps the public API surface of each endpoint intentional.
Default ordering is part of the contract. Always declare a fallback sort so unsorted requests are deterministic — otherwise pagination over an unordered result set will duplicate and drop rows between pages. With multi-column sorts, the last column in the chain should be a unique tiebreaker (typically the primary key).
Multi-sort with direction prefixes. Follow the convention the package uses for descending (commonly a - prefix) and validate the whole string before applying. Cap the number of sort segments accepted from the client — a dozen orderBy clauses will quietly kill your query plan.
Sorts that aren't columns. For computed or related fields (comment count, latest related record's timestamp, a CASE expression), use the package's custom-sort extension point rather than joining in the controller. If a sort requires a join, add the join inside the sort definition so the query shape stays consistent between filtered and unfiltered requests.
Compose with filters and pagination, not around them. Apply the sort definition to the same builder that filtering and pagination consume (or use the package's own paginate entry point). Mixing a package-built query with a hand-built ->paginate() on a second builder is a common source of "the sort works but the page count is wrong".
Tests that actually lock behaviour. Cover: default sort when no parameter is sent, each whitelisted sort in both directions, a rejected/ignored invalid column, and a multi-sort case. Assert on the generated SQL or on the returned id ordering with a seeded fixture — SQL snapshot tests catch tiebreaker and ambiguity regressions cheaply.
Version pinning and upgrade hygiene. Because minor releases have added new sortings, keep the lockfile committed and run your sort test suite on upgrade. If your API exposes an endpoint that enumerates available sorts to a frontend, that list may grow on a minor bump — treat it as additive and make the frontend tolerant of unknown values.
orderBy('created_at') against a query with two joined tables will error or pick the wrong table. Qualify with the table name or use the alias in your sort definition.select alias works in MySQL but not reliably in PostgreSQL; re-declare the expression in the orderBy instead.- prefix convention means the raw value is -column; don't pass that straight into orderBy($column, 'desc') without stripping the prefix first — the classic symptom is Unknown column '-name'.EXPLAIN for the sorts your UI actually uses and add composite indexes for the common WHERE ... ORDER BY ... pairs.is_published) mean row order is not stable across pages. Always append the primary key.with() collections; those need a closure with their own orderBy. Otherwise the API looks "half sorted" and the bug is reported as a sorting bug.->toSql() and the bindings before pagination. Most sorting surprises are a missing join or a silently dropped clause, not a package bug.php artisan config:cache during deploy — a locally-working new sort list that "doesn't exist" in production is almost always a stale config cache.How can I help you explore Laravel packages today?