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

Laravel Query Strategies Laravel Package

myerscode/laravel-query-strategies

myerscode/laravel-query-strategies provides reusable, composable query strategies for Laravel Eloquent models, helping you encapsulate filtering, sorting, and search logic to keep controllers clean and queries testable.

View on GitHub
Deep Wiki
Context7

Getting Started

This release is a large feature drop for myerscode/laravel-query-strategies, turning it from a basic query-parameter handler into a fairly complete query-strategy layer for Laravel APIs. It targets Laravel 13 / Testbench 11, so treat 13.0.0 as a hard version bump alongside the feature work.

Minimal path:

  1. composer require myerscode/laravel-query-strategies and confirm your app is on Laravel 13. If you are still on Laravel 11/12, stay on the previous major.
  2. Publish the config (php artisan vendor:publish for the package config) and skim it before touching code — strict mode, defaults, and strategy resolution all live there.
  3. Create a strategy class for your first model and declare the filters/sorts/includes it allows.
  4. Attach the strategy to a controller action (directly or via the model auto-pickup added in this release) and return the paginated result.

First use case: an index endpoint such as GET /api/posts?filter[status]=published&sort=-created_at&include=author,comments&fields[posts]=id,title. That single request exercises filtering, sorting, relationship includes, and field selection — the core of the new feature set. Start with filters + sorting only, then layer in includes and field selection once the basics round-trip.

Where to look first: the strategy base class (to see defaultMethods and how parameters map to clauses), the clause classes under the filter namespace, and the config file. The clause classes are the best documentation of what query-string syntax the package actually accepts.

Implementation Patterns

One strategy per model, with model auto-pickup. Rather than wiring every controller manually, define a strategy class per Eloquent model and let the new default-model-strategy / auto-pickup behaviour resolve it. This keeps the allowed-filter surface next to the model it protects and removes repetitive controller plumbing.

Compose filters from clauses, not closures. The release adds BetweenClause, IsNull/IsNotNull, TrashedClause, and ScopeClause. Prefer these over ad-hoc logic:

  • Ranges: filter[created_at][between]=2024-01-01,2024-12-31
  • Null checks: filter[deleted_at][is_null]=1
  • Soft deletes: TrashedClause for withTrashed/onlyTrashed toggles on models using SoftDeletes
  • Domain scopes: ScopeClause to expose an existing scopePublished() etc. as a query parameter — this is the cleanest way to reuse business logic you already have.

Relationship filtering and nested sorting. Filters and sorts can now traverse relations (e.g. sort=author.name, filter[author.status]=active). Use this instead of hand-rolled whereHas in controllers, but keep an eye on the generated SQL for deep paths.

Aggregate relationship includes. For list screens that show counts (comment counts, like counts), use the aggregate include support rather than loading full relations and counting in PHP.

Field selection (sparse fieldsets). fields[posts]=id,title lets clients trim payloads. Pair this with append support for accessors so computed attributes (full_name, url) are only serialized when explicitly requested.

Callback / inline filters. For the one-off case that does not deserve a clause class, register a closure filter. Keep these few — they are invisible to static analysis and easy to duplicate.

Defaults and ignore lists. Use default filter values so an omitted parameter resolves to a sane baseline, and the ignored-values list so sentinel values like '', all, or null are treated as "no filter" rather than literal matches. This is the difference between a filter that behaves well in a UI and one that returns zero rows.

Opt-in strict mode. Enable strict mode once your strategies are stable. It converts unknown/undeclared parameters from silent no-ops into hard failures — invaluable during client development, mildly hostile in production if clients send experimental params. Roll it out per-environment first.

Shorthand clause mapping. Parameters can reference a clause class via a shorthand instead of the fully-qualified name. Use it in user-facing docs and client SDKs; keep the FQCN in code where clarity matters.

Gotchas and Tips

  • Major-version coupling. 13.0.0 brings Laravel 13 / Testbench 11. Plan the framework upgrade and the package upgrade together; do not expect the previous major to receive these features.
  • Parameter is now readonly. Any code that mutated a parameter object in place will break. Construct a new instance instead. If you have custom clause implementations, audit them for property writes.
  • StrategyManager no longer double-instantiates strategies. If you relied on constructor side effects firing twice (or worked around them), remove the workaround. Strategy constructors should be side-effect free anyway.
  • defaultMethods map is cached. The compiled map is memoised for performance. If you mutate strategy definitions at runtime (feature flags, tenant-specific filters), clear or bypass the cache explicitly — otherwise your changes will not take effect on subsequent requests in the same process.
  • Redundant limit() before paginate() was removed. If your strategy added a limit for "safety", pagination totals and page counts may shift. Verify total() and last-page behaviour after upgrading.
  • Eager-load relationship names are now validated. include=author where author is not a real relation will fail instead of silently doing nothing. That is better, but it can surface latent typos in existing clients — roll out with logging first.
  • Trashed requires SoftDeletes. TrashedClause is meaningless on a model without the trait; expect either an exception or a silently ignored parameter depending on strict mode.
  • Field selection can strip required columns. If your resource/transformer needs id or a foreign key, either append it server-side or document that clients must request it. Missing keys produce confusing null attributes rather than clear errors.
  • Deep relation paths cost queries. Nested sorting and relationship filtering generate joins/subqueries. Check EXPLAIN on large tables and add indexes on the relation's join columns before exposing these to clients.
  • Strict mode changes error semantics. Turning it on will break clients that send stale parameters. Log rejected parameters for a release cycle before enforcing.
  • Debugging tip: dump the underlying builder (->toSql() / ->getBindings(), or DB::listen) for a representative request before and after upgrading. This is the fastest way to spot the removed-limit and changed-relation-validation behaviour.
  • Extension points worth knowing: custom clause classes (register via the shorthand mapping), the strategy resolution path for model auto-pickup (override if you use multi-tenant or namespaced models), and the package config for strict mode, defaults, and ignore lists. Prefer a custom clause over a callback filter when the logic is reused in more than one strategy.
  • Static analysis is now clean at Larastan level 8. If you extend package classes, you should be able to hold your own code to the same level — useful signal that the public API is reasonably typed.
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.
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core