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

Searches Laravel Package

sloth-dev-guy/searches

A Laravel package for adding reusable search functionality to your models and queries. Configure searchable fields, run flexible filtered searches, and get clean, query-builder-friendly results without repeating boilerplate code across your app.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and confirm it still boots on your stack first. The package has had no release since August 2022 and zero dependents, so treat installation as an evaluation, not a routine composer require:

composer require sloth-dev-guy/searches

Before writing any feature code, check composer.json in vendor/sloth-dev-guy/searches for illuminate/* constraints and the PHP requirement. If you're on Laravel 10/11 or PHP 8.2+, expect to either pin an older Laravel for a spike or fork the package locally (repositories → path/vcs) and patch the constraints yourself. A zero-star package with no dependents means you are the maintainer the moment you ship it.

Where to look first. Read in this order:

  1. src/ — the service provider (config merge, any bindings/macros) and the trait/scope that models actually use. This is the whole package; it is small enough to read end to end in ten minutes.
  2. README.md at the repo root for the expected query-string shape (the "array like API notation" — e.g. ?filters[name][like]=jo&filters[created_at][gte]=2024-01-01).
  3. config/ if published, for the operator map and any default field allowlist.

First use case. The natural entry point is a single index endpoint where you want filterable, sortable lists without hand-writing a match block per column:

// app/Models/Invoice.php
use SlothDevGuy\Searches\...; // confirm the exact trait name in src/

class Invoice extends Model
{
    use Searchable;

    protected array $searchable = ['number', 'status', 'total', 'created_at'];
}
// Controller
public function index(Request $request)
{
    return Invoice::search($request->query())
        ->paginate(25)
        ->withQueryString();
}

Get that working against one model and one endpoint before rolling it out — the value proposition is entirely in whether the package's operator parsing matches the filter syntax your frontend already sends.

Implementation Patterns

Allowlist at the model, not the controller. The core risk with any array-driven query notation is a client passing ?filters[password][like]=a. Define searchable fields as a property (or override the resolving method) so unknown keys are dropped rather than reaching the query builder. This is the pattern you should enforce in review across every model.

Map the operator vocabulary to your API contract once. Whatever the package exposes (eq, like, in, gte, lte, between, null), write it down in your API docs and stick to it. Frontends that generate filter payloads from a table component will hard-code these strings; drift here is the most common source of "the filter silently does nothing" bug reports. If the package's built-in set is missing something, add a custom operator handler via the package's extension point rather than special-casing in the controller.

Keep the controller thin and the scope composable. Chain package search with your own scopes so authorization and tenancy stay outside the package's concern:

Invoice::query()
    ->whereBelongsTo($request->user()->team)
    ->search($request->validated('filters', []))
    ->when($request->boolean('trashed'), fn ($q) => $q->withTrashed())
    ->paginate(25);

Run filters through FormRequest validation ('filters' => ['array'], plus per-key rules if you want strict operator validation) so malformed input fails with a 422 instead of an exception from deep in the builder.

Persist filter state in the URL. Always pair ->paginate() with ->withQueryString() (or appends()), otherwise page 2 loses every filter. Same rule for any "export CSV" or "save view" feature — serialize the same array shape the package consumes.

Relationship filters need explicit thought. If the package supports dotted/whereHas notation, prefer it over joins for filtering (no duplicate rows), and reserve with() for the eager loading actually rendered by the response. Watch for the classic combination of a whereHas filter plus withCount on the same relation — it's correct but often doubles the query count.

Test at the query level, not the response level. For each supported operator, assert with DB::listen or ->toSql()/bindings that the filter produced the expected clause, then one or two end-to-end feature tests per resource. Snapshotting raw JSON responses will break on every unrelated model change.

Gotchas and Tips

  • Abandonment is the headline risk. Last release 2022-08-15, 0 stars, 0 dependents. Budget for a fork on day one: vendor it into packages/ via a path repository, or copy the trait into app/Support/. The codebase is small enough that owning it is cheaper than hoping for upstream fixes.
  • Column injection. Array notation means user-controlled keys. Never pass $request->all() into the search method without an allowlist — validate keys against the model's $searchable and reject/ignore the rest. If the package accepts a raw column name from input anywhere (sorting is the usual suspect), sanitize it with Schema::hasColumn() or an explicit mapping.
  • Query-string encoding. Nested array notation requires filters[name]=x&filters[status][in][]=paid; brackets are legal unencoded in practice but some HTTP clients and proxies mangle them. If filters mysteriously empty out, log $request->query() at the controller before blaming the package.
  • Case sensitivity and collation. LIKE matching depends on the DB collation (utf8mb4_unicode_ci is case-insensitive on MySQL, Postgres ILIKE is not LIKE). A "works locally, not in staging" search bug is almost always this or a missing index.
  • Indexes. LIKE '%term%' cannot use a B-tree index. If the search fields are high-cardinality and traffic is real, plan for a full-text index (FULLTEXT, Postgres tsvector, or Scout/Meilisearch) rather than scaling the package's LIKE behaviour.
  • Debugging. Wrap the search call in DB::listen(fn ($q) => logger($q->sql, $q->bindings)) when a filter returns the whole table — it's usually an unrecognised operator name falling through to a no-op rather than a real bug.
  • Extension points to look for: the operator/keyword map (in config or a static property), any macroable builder, and the method that resolves searchable columns. Those three are where you should make changes; editing the trait's internals in vendor/ is a trap that dies at the next composer install.
  • Version pinning. With no releases since 2022, use an exact version ("sloth-dev-guy/searches": "1.0.x") or a VCS/path reference to a commit you've reviewed, and add a composer.lock review step — an accidental composer update shouldn't be able to swap this dependency's behaviour.
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.
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
noith/settings
kda/laravel-package