yaknet / mock-engine
In-memory SQL-like query builder and execution engine for PHP arrays
Requires
- php: >=8.1
Requires (Dev)
- phpstan/phpstan: ^2.2
- phpunit/phpunit: ^10.0
README
MockEngine is a lightweight, pure PHP (PHP 8.1+) in-memory query engine that lets you filter, sort, join, group, and aggregate raw arrays or object lists using an elegant, Laravel/Symfony-style fluent Query Builder—completely without any database overhead!
It is perfect for unit testing, in-memory caching systems, sorting baskets in e-commerce, or managing nested datasets in microservices.
Features
- ✨ Fluent Query Builder: Build queries using
where(),orWhere(),select(),orderBy(),limit(),groupBy(),join(), andleftJoin(). - 🎯 Point Notation (Nested Access): Query nested arrays or objects instantly, e.g.,
where('profile.address.city', '=', 'Istanbul'). - ⚙️ Advanced Operators: Support for
=,!=,>,<,>=,<=,LIKE,NOT LIKE,IN,NOT IN,BETWEEN, andNOT BETWEEN. - 🔗 Relation Joins: Easily perform
INNER JOINandLEFT JOINoperations across different arrays or object collections. - 🗃️ Group By & Collections: Group results automatically, and utilize the built-in
Collectionwrapper for powerful aggregations (sum,avg,min,max,pluck). - 🚀 Zero Dependencies: Written entirely in pure, highly-optimized PHP.
Installation
Install the package via Composer:
composer require yaknet/mock-engine
Quick Start
1. Basic Filtering
use YakNet\MockEngine\QueryBuilder; $users = [ ['id' => 1, 'name' => 'John Doe', 'role' => 'admin', 'profile' => ['city' => 'Istanbul']], ['id' => 2, 'name' => 'Jane Smith', 'role' => 'user', 'profile' => ['city' => 'Ankara']], ['id' => 3, 'name' => 'Bob Johnson', 'role' => 'user', 'profile' => ['city' => 'Izmir']], ]; // Query active admins in Istanbul $results = QueryBuilder::from($users) ->select('id', 'name', 'profile.city as city') ->where('role', '=', 'user') ->where('profile.city', '!=', 'Ankara') ->get(); // Returns a Collection containing: // [ ['id' => 3, 'name' => 'Bob Johnson', 'city' => 'Izmir'] ]
2. Complex & Nested Logical Groups (AND / OR)
You can group logical operations together by passing a Closure to where or orWhere:
$results = QueryBuilder::from($users) ->where('status', '=', 'active') ->where(function (QueryBuilder $query) { $query->where('role', '=', 'admin') ->orWhere('profile.verified', '=', true); }) ->get();
3. Joining Two Collections (INNER / LEFT JOIN)
$posts = [ ['id' => 101, 'user_id' => 1, 'title' => 'First Post'], ['id' => 102, 'user_id' => 1, 'title' => 'Second Post'], ['id' => 103, 'user_id' => 2, 'title' => 'Hello World'], ]; // Perform INNER JOIN $results = QueryBuilder::from($users) ->select('name', 'title') ->join($posts, 'id', '=', 'user_id') ->get();
4. Grouping & Collection Aggregations
If you use groupBy(), the results will be grouped into a nested Collection of Collections:
$grouped = QueryBuilder::from($users) ->groupBy('profile.city') ->get(); // Get the average age of users in Istanbul $istanbulUsers = $grouped['Istanbul']; // This is a Collection! $averageAge = $istanbulUsers->avg('age'); $maxAge = $istanbulUsers->max('age'); $names = $istanbulUsers->pluck('name'); // ['John Doe', ...]
Running Tests
All features are fully verified with a comprehensive unit test suite:
vendor/bin/phpunit
License
This project is licensed under the MIT License. See LICENSE.md for details.