djl997/laravel-search-query-builder
A Laravel package offering a fluent query builder for composing search filters and database queries, helping you keep complex search logic clean, reusable, and easy to maintain across your application.
search() layer on Laravel's query builder. It directly supports shipping basic column-based filtering in admin panels, internal tools, list/reporting endpoints, and back-office dashboards — the "good enough" tier of search that does not justify a search service.WHERE ... LIKE assembly in every controller. Adopting this package trades a small dependency for less bespoke query code to maintain, test, and review. 1.4.0 materially improves the buy case: the package now has a test suite and a CI matrix, which was previously the main reason to prefer in-house code."foo,", "foo,,bar", whitespace-only) is a product-visible defect: a filter that silently returns every row reads to users as "the filter is broken" or, worse, surfaces records a filtered view is expected to hide. Treat this as a data-exposure-adjacent fix, not a cosmetic one.Adopt when:
DB::table()/Eloquent queries with a column list we control in code, not user-supplied column names. The new grammar-based quoting makes reserved-word columns (order, group) safe, and the removal of raw column expressions narrows the injection surface — both are favorable for this use case.search() returning null fix means it can sit mid-pipeline (->search(...)->where(...)->paginate()), which is the pattern most list endpoints use. Prior to 1.4.0 this was not safe to build on.LIKE-style filtering is acceptable — no relevance scoring, no typo tolerance, no faceting.Look elsewhere when:
CONCAT(first_name, last_name), COALESCE(...)). This is a hard break in 1.4.0 with no stated migration path. Audit for it before committing to the upgrade; if it's in use, either refactor to a computed/virtual column or choose a different approach.LIKE '%term%' scans are a performance problem; this package does not address indexing strategy or cursor-based pagination.^1.4 and avoid back-reviving older versions in existing services.To executives: This is a small, narrowly scoped dependency that replaces hand-written filtering code in our list views and admin tools. The new release is a stabilization pass: it fixes three real bugs — one where a malformed search term returned every record instead of filtering, one that broke on columns named with SQL reserved words, and one that prevented chaining further query conditions. It also adds automated tests and continuous integration across Laravel 9 through 13, which reduces our long-term maintenance exposure. There is one breaking change: any code passing raw SQL expressions as search columns must be refactored first. Cost is low; the main work item is a one-time audit of existing usages.
To engineering: Pin to ^1.4.0. Three behavior changes to account for: (1) search() now returns the builder — remove any null-guards or workarounds added around it; (2) column names are now quoted by the grammar, so reserved-word columns work but raw expressions like CONCAT(...) are no longer supported — grep for these and replace with generated/virtual columns or an explicit selectRaw outside the search call; (3) empty and whitespace-only terms — including comma-separated lists with empty segments — no longer match all rows, so any UI or test that relied on that fallthrough behavior needs updating. Test and CI coverage is new as of this release, so treat 1.4.0 as the first version we can rely on and do not assume equivalent guarantees from earlier tags.
How can I help you explore Laravel packages today?