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 Natural Where Laravel Package

divineomega/laravel-natural-where

Laravel Natural Where adds expressive, human-readable where clauses to Laravel's query builder, letting you define filters in natural language instead of complex nested conditions. These simple helpers make Eloquent queries easier to write, read, and maintain in Laravel apps.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Install with composer require as usual; the service provider is auto-discovered and registers the natural-sort macros on the query builder, so there is no manual app.php entry on modern Laravel. On the older end of the support matrix (5.6/8) check whether the package's docs still ask you to register the provider manually.
  • Look first at the macro registration class (typically the package's service provider or a dedicated Macros/QueryBuilder class). That file tells you the exact macro names, argument order, and whether column names are validated — which matters more than the README for day-to-day use.
  • Your first use case is almost always a search box or an admin listing: Item::query()->naturalOrWhere('name', 'like', "%{$term}%")->get() or ->naturalOrderBy('title'), giving you "Item 2" before "Item 10" instead of lexicographic ordering.
  • v3.1.0 explicitly adds Laravel 13 support. Before upgrading, run composer why-not / check the constraint to confirm your Laravel version (9–12 are not named in the notes) is still inside the allowed range, and that the transitive illuminate/* constraints resolve.

Implementation Patterns

  • Group OR conditions. naturalOrWhere is an orWhere under the hood, so a bare call after an existing where will widen the result set. Wrap it:

    $query->where('tenant_id', $tenant->id)
          ->where(function ($q) use ($term) {
              $q->naturalOrWhere('name', 'like', "%{$term}%")
                ->naturalOrWhere('sku', 'like', "%{$term}%");
          });
    
  • Chain directly now. The v3.1.0 fix makes naturalOrWhere return the builder result, so return $query->naturalOrWhere(...)->paginate(25); works. If you had a workaround ($query->naturalOrWhere(...); return $query;, or a temporary variable purely to dodge a null return), remove it — leaving it in makes the code misleading for the next reader.

  • Pair sorting with a tiebreaker. Natural ordering produces ties for human-identical strings ("item 2" vs "Item 2"). Add ->orderBy('id') after the natural order so pagination is deterministic and cursorPaginate doesn't skip/duplicate rows between pages.

  • Encapsulate in scopes. Put the multi-column search behind a local scope (scopeSearch) or a shared macro so the grouping discipline is enforced in one place rather than re-derived in every controller.

  • Compose with existing query builders. The macros operate on Illuminate\Database\Query\Builder, so they work inside Eloquent, DB::table(), and relations — useful for whereHas constraints where you want a natural match on a related model's column.

  • Test the generated SQL, not just results. Feature tests against SQLite will pass while production MySQL/Postgres differs; add ->toSql()/->getBindings() assertions for any non-trivial composition, and at least one integration test on the production driver.

Gotchas and Tips

  • Expression-based ordering can't use an index. Natural sort typically compiles to LENGTH()/CAST()/REGEXP/collation tricks. ORDER BY on an expression forces a filesort; with offset pagination on large tables this degrades badly. Mitigate with a generated/stored sort column, a narrower filtered set, or cursor pagination.
  • Whitelist column names. If the column comes from request input (?sort=name), validate it against an allow-list. Binding protects values, not identifiers; the package may or may not quote identifiers for you — verify in the macro source before trusting it.
  • Collation and case sensitivity vary by driver. LIKE is case-insensitive on default MySQL collations but case-sensitive on Postgres; SQLite comparisons differ again. Any behaviour you rely on (accent handling, case folding) needs a test on the real driver.
  • The naturalOrWhere return-value fix is a silent behavioural change. Call sites that depended on the previous null/void return — ternaries, truthiness checks, if ($result = $query->naturalOrWhere(...)) — will now behave differently. Grep for the macro before bumping and audit each hit; this is the main upgrade risk in v3.1.0, and it is not a BC break for correct code.
  • Wide version matrix means conditional code paths. Supporting 5.6 through 13 in one branch implies version sniffing internally. When filing an issue, always include Laravel version, PHP version, and DB driver/version — otherwise the maintainer can't reproduce.
  • Debugging tip: log ->toSql() and ->getBindings() at the point of failure rather than the final SQL from the query log; it shows whether the macro expanded before or after your grouping closure was applied.
  • Extension points: prefer registering your own thin wrapper macro (e.g. searchNatural) over forking, and if the package exposes a comparator/collation config, publish it rather than editing vendor files — the 5.6→13 support range means internals are more likely to shift than the public macros.
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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
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