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 Scout Builder Laravel Package

foxws/laravel-scout-builder

A fluent query builder for Laravel Scout that lets you construct search queries with familiar chainable methods, making it easier to filter, sort, and paginate searchable Eloquent models while keeping Scout integrations clean and expressive.

View on GitHub
Deep Wiki
Context7

Getting Started

foxws/laravel-scout-builder sits on top of Laravel Scout and gives you a fluent, object-oriented way to build the driver-specific filter expressions (Meilisearch, Typesense, Algolia) that you would otherwise hand-write as strings inside ->where(...). This assessment reflects v1.2.0.

  1. composer require foxws/laravel-scout-builder
  2. Publish any shipped config if present: php artisan vendor:publish --tag="scout-builder-config"
  3. Confirm Scout itself is configured (config/scout.php) and your model uses Laravel\Scout\Searchable.
  4. Look first at the builder entry point and the filter/operator resolution code — that is where 90% of the behaviour you'll care about lives.

The first use case to reach for: any endpoint where filter input is user-driven (?price_min=…&status=…&rating>=4). Instead of concatenating filter strings and hoping the syntax is valid, you declare filters and let the package compile them. If you're currently doing Model::search($q)->where('price > 100 AND status = "active"'), that's the code to migrate first — it is exactly where malformed input, unescaped quotes, and injection-shaped bugs come from.

Implementation Patterns

Filter-per-concern classes. Define a filter class per model or per index (status, price range, date range, owner). This keeps the builder declarative and testable, and lets the package normalise nullability and operator tokens in one place.

Pass everything, let nulls no-op. The dominant pattern after 1.2.0 is to always hand the builder the full set of filters, including ones the user didn't supply. A nullable filter whose value is null is now fully ignored, so it drops out of the compiled expression instead of producing an empty or = "" constraint. This removes a whole layer of if ($request->filled(...)) branching from your controllers.

Dynamic operator tokens. Filters that accept tokens embedded in the value (e.g. >=500, !=draft) are resolved by the package. As of 1.2.0, an unrecognised operator token no longer breaks or silently miscompiles the query — it degrades to equality. Treat the token map as a whitelist you control, not as free-form input validation.

Composition. The typical call site reads as: build for a model → attach the filter set → attach the search term → get()/paginate(). Keep the builder in a form request or a dedicated query object so the compiled expression is reproducible in tests.

Testing. Assert on the compiled filter string (or the builder's toArray()/__toString() equivalent) rather than hitting the search engine. This is fast, deterministic, and is the only practical way to catch regressions in operator resolution — including the 1.2.0 fallback behaviour.

Reuse across drivers. Because the builder owns the quoting/escaping, the same filter definitions can target Meilisearch in one environment and Typesense in another. Centralise escaping there and never interpolate raw user input into a where() call alongside it.

Gotchas and Tips

  • 1.2.0 is a behaviour change, not just a bugfix. Unknown dynamic operator tokens now silently fall back to equality instead of failing or being dropped. If you were relying on an exception, an empty constraint, or a validation error to reject bad input, that safety net is gone — validate operator tokens yourself before they reach the builder.
  • "Fully ignored" is all-or-nothing. A filter is skipped only when every clause it contributes is ignorable. A multi-clause filter with one null part will still emit the remaining clauses. Don't assume a null anywhere means the filter disappears.
  • Null is not empty string. null is skipped; "" and 0 are values and can still generate constraints (status = ""). Normalise '' to null in your request layer if the UI sends empty fields.
  • Quote escaping with spaces. Values containing spaces or reserved characters must be quoted by the builder. If you've hand-wrapped a value in quotes and pass it through the builder, you'll get double-quoting and a filter that matches nothing. Pass raw values only.
  • Silent degradation hides typos. =>500 (typo for >=500) now compiles to equality against the literal string. When a filter "returns no results", dump the compiled expression before suspecting the engine.
  • Debug by dumping the expression. Always log the final compiled filter string on the failing request; it is the single most useful artefact when a query behaves unexpectedly.
  • Extension points. Custom operator handling and per-filter normalisation are the intended seams — prefer subclassing or registering a custom filter over subclassing the builder itself, which is the piece most likely to churn between releases.
  • Nested/relationship filters compile differently per driver (Meilisearch's dot-notation vs. Typesense's nested field syntax). Verify any deeply nested filter against each engine you actually deploy to, not just your local one.
  • Pin the version if you depend on the pre-1.2.0 fallback semantics, and add a test that asserts your expected behaviour for an unknown token so a future patch doesn't quietly change it again.
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.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource