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

Array Query Laravel Package

mauretto78/array-query

Array Query is a PHP library that lets you query arrays using SQL-like syntax: select, where, order by, group by, limit and joins, with support for nested keys and custom operators. It brings database-style filtering and sorting to plain arrays, making complex data manipulation readable and testable...

Deep Wiki
Context7

Getting Started

Install and pin. The package is stable-name but low-traffic, so install with an explicit constraint rather than ^1.0 blind:

composer require mauretto78/array-query
composer show mauretto78/array-query   # check the PHP constraint before you commit

The last tagged release is from October 2019, so the first thing to verify is whether the declared PHP requirement accommodates your runtime (7.4 vs 8.2+). If it doesn't, you can still install with --ignore-platform-reqs for a spike, but treat that as a red flag for production use.

Where to look first, in order:

  1. README.md — the usage section is the only real documentation; read it end-to-end because the operator list and method names are the whole API surface.
  2. src/ — there are only a handful of classes; the query/builder class and any operator or comparator class are where the semantics live.
  3. tests/ — this is your authoritative spec. When the README is ambiguous about type coercion, LIKE behaviour, or nested-key access, the test suite answers it faster than experimentation.

First use case. The natural fit is filtering a decoded payload — a JSON API response, an imported CSV, a config tree — where you want declarative, SQL-shaped filtering without standing up a database or writing nested array_filter closures:

use ArrayQuery\ArrayQuery;

$rows = json_decode(file_get_contents('orders.json'), true);

$results = (new ArrayQuery($rows))
    ->where('status', '=', 'paid')
    ->where('total', '>', 100)
    ->orderBy('total', 'DESC')
    ->limit(20)
    ->get();

Confirm the exact constructor and chain method names against the README before building on them — the shape above is the conventional one for this class of library, not a guarantee.

Implementation Patterns

Wrap it, don't sprinkle it. The library is a thin, unmaintained dependency. Isolate it behind your own repository or service class so that swapping to Illuminate\Support\Collection, nicolasgraph/array-query, or a real query builder later is a one-file change:

final class OrderQuery
{
    public function paidOver(float $min): array
    {
        return (new ArrayQuery($this->rows))
            ->where('status', '=', 'paid')
            ->where('total', '>', $min)
            ->get();
    }
}

This also gives you a place to normalise input (see Gotchas) before the library ever sees it.

Build conditions incrementally. The value of a query builder over array_filter is conditional composition — appending predicates only when a filter is actually supplied, which maps cleanly onto request-parameter filtering:

$query = new ArrayQuery($rows);
if ($status = $request->input('status')) {
    $query->where('status', '=', $status);
}
if ($min = $request->input('min_total')) {
    $query->where('total', '>=', (float) $min);
}
$results = $query->get();

Use dot notation for nested structures. Multidimensional access is the package's reason to exist; reach for customer.address.country-style keys rather than flattening your data first. Verify the separator and whether missing intermediate keys throw or evaluate false — that difference decides whether you need a normalisation pass.

Reach for sorting/limit as a pagination stand-in. Slice after ordering to emulate LIMIT/OFFSET for small in-memory sets (dashboards, exports, CLI reports). Above a few thousand rows this becomes the wrong tool — see below.

Integrate at the edges of Laravel, not the middle. Good placements: a console command transforming an imported file, a test fixture builder, a read-only reporting endpoint over cached JSON. Bad placements: anything inside a request loop, or as a substitute for an Eloquent relationship you already have.

Pair with aggregates for reporting. If the package exposes sum/avg/min/max/count helpers, a single pass with a grouped aggregate beats filtering the array several times in application code.

Gotchas and Tips

Maintenance is the headline risk. A single 2019 release, 12 stars, and an unlisted repository means no security response and no PHP 8.x compatibility work. Budget for the possibility that you own this code. Run the test suite (vendor/bin/phpunit) immediately after install — a green suite on your PHP version is the only real compatibility signal you'll get.

Type coercion at comparison boundaries. PHP's loose comparison makes '10' > 9 and 'abc' == 0 behave in ways that will surprise you. Cast inputs explicitly before they enter the query, and prefer the library's strict-comparison operator if one exists. Write a test for the 0/null/'' cases, which are the classic false-positive trio.

Missing keys break predicates. Heterogeneous rows — some with total, some without — will produce notices or silently drop rows depending on the implementation. Normalise the dataset up front: fill defaults with array_map(fn($r) => $r + $schema, $rows) before querying.

Dot notation collides with literal dots. If any of your array keys legitimately contain . (common in config keys and MIME types), nested access will misparse them. Flat keys or a different separator are the workarounds.

Performance is linear and unindexed. Every where walks the array; chaining N predicates is O(N·M) over M rows. For anything beyond a few thousand records, convert to a Collection or push the filter into the source system. Do not benchmark-guess — measure with microtime(true) around a realistic payload, because the cost of the library may be dominated by PHP's array copying anyway.

Watch for copy semantics. Confirm whether get() returns a fresh array or the internally mutated one. Sharing a query object across scopes and mutating it is the fastest way to produce a stale-result bug that looks like a data problem.

Debugging. There is almost certainly no query logging. Dump the intermediate array after each where to localise which predicate is dropping rows; when nothing matches, check operator spelling against the operator list in src/ rather than the README, since they can drift.

Extension points. If the design supports registering custom operators or comparators, that is the clean way to add domain rules (e.g. currency-aware comparison) without forking. If it doesn't, keep custom logic in your wrapper class rather than patching vendor/.

Know when to stop. For simple flat filtering, collect($rows)->where('status', 'paid') in Laravel is better maintained and better understood by your team. Adopt this package specifically when its multidimensional dot-path querying saves you real code — and write the wrapper so that advantage is reversible.

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.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core