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

Basic Query Filter Laravel Package

ralphschindler/basic-query-filter

A lightweight Laravel package for applying request-driven filters to Eloquent queries. Map query-string parameters to allowed columns and operators, keeping filtering logic out of controllers and list endpoints predictable and reusable.

View on GitHub
Deep Wiki
Context7

Getting Started

Install via Composer (expect to need --ignore-platform-reqs on modern PHP; the last release was 2017):

composer require ralphschindler/basic-query-filter

First, inspect vendor/ralphschindler/basic-query-filter/src/ and tests/ to learn the actual entry point. The package is a parser only — it does not execute filters against a database. Look for a Parser, Lexer, or Filter class. A typical first use case is parsing a request query string such as:

status = 'active' AND created_at > '2024-01-01'

into a token tree/AST that you then translate into Eloquent where clauses. Start with a tiny script or Artisan tinker session:

$parser = new \BasicQueryFilter\Parser(); // confirm class name from src/
$ast = $parser->parse("status = 'active' AND age > 18");
dump($ast);

Once you can dump the AST, write a small evaluator that maps its nodes to Laravel query builder calls. Do not try to use the package directly as a query builder — it is a language parser, not an ORM integration.

Implementation Patterns

Wrap parsing and application in a dedicated service. Keep the parser isolated from Eloquent so you can test grammar separately from query generation.

namespace App\Filters;

use BasicQueryFilter\Parser; // adjust namespace after inspecting package

class QueryFilter
{
    public function __construct(private Parser $parser) {}

    public function apply($query, string $filter): void
    {
        if (trim($filter) === '') {
            return;
        }

        $ast = $this->parser->parse($filter);

        $query->where(function ($q) use ($ast) {
            $this->applyNode($q, $ast);
        });
    }

    private function applyNode($query, $node): void
    {
        // Map the package's AST node types to where/orWhere/etc.
        // Example shape depends on the package — inspect with dd() first.
    }
}

Whitelist columns and operators. Maintain arrays like $allowedColumns = ['status', 'created_at', 'age'] and $allowedOperators = ['=', '!=', '>', '<', '>=', '<=', 'LIKE']. Reject anything else with a 400 response.

Use in a controller or form request.

public function index(Request $request, QueryFilter $filter)
{
    $query = User::query();

    try {
        $filter->apply($query, $request->query('filter', ''));
    } catch (\Throwable $e) {
        abort(400, 'Invalid filter syntax.');
    }

    return $query->paginate();
}

Prefer a query scope for reuse.

public function scopeFiltered($query, string $filter)
{
    app(QueryFilter::class)->apply($query, $filter);
    return $query;
}

Handle nested AND/OR recursively. If the parser returns a binary tree, write applyNode() to detect logical nodes and recursively call where() or orWhere() with closures. For grouped expressions, pass a closure to where() so Laravel adds parentheses correctly.

Keep value binding safe. Always pass values as bindings, never concatenate into whereRaw():

$query->where($column, $operator, $value); // safe

Test parser output separately from SQL. Use PHPUnit to assert the AST shape for representative filters, then feature-test endpoints with assertDatabaseHas or by inspecting toSql() and getBindings().

Gotchas and Tips

  • The package is unmaintained (2017). Expect PHP 8 incompatibilities, missing type declarations, and possibly deprecated syntax. Test installation early; if Composer blocks it, either use --ignore-platform-reqs or fork the package and relax composer.json constraints.
  • No Laravel integration. There is no service provider or facade. Bind the parser manually in a service provider or resolve it through the container with a factory closure.
  • Parser only, not an executor. You must write the translation layer from AST/tokens to Eloquent. Do not assume the package understands SQL semantics, operator precedence, or database-specific behavior.
  • Check the grammar in tests/. The supported syntax may be narrower than you expect — for example, quoted strings with spaces, escaped quotes, case-insensitive operators, or IN (...) may not parse. Validate against your real filter strings before committing to the package.
  • Security: Never pass user-supplied column names directly to orderBy, select, or whereRaw. Whitelist columns and operators. Treat the filter string as untrusted input even though the parser is doing the parsing.
  • Error handling: Parsing may throw generic exceptions. Catch them at the controller boundary and return a 400 rather than a 500. Log the original filter string for debugging.
  • Debugging: Dump the AST with dd() or var_dump() in a route closure during development. After building the query, inspect ->toSql() and ->getBindings() to confirm parentheses and parameter order.
  • Empty filters: Short-circuit on empty or whitespace-only strings; a parser may throw or return an invalid node.
  • Performance: Parsing per request is usually fine, but cap filter length and consider caching parsed filters if clients send identical complex filters repeatedly.
  • Extension points: If the grammar is too limited, inspect whether the lexer/parser can be subclassed. Because the package is small and Unlicense-licensed, forking or copying the parser into app/ is often more practical than waiting for upstream changes.
  • License: Unlicense means public domain — commercially usable, but no warranty or support. Pin the version in composer.json and document the fork/upgrade path for your team.
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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
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