adachsoft/dynamic-table-in-memory

In-memory (RAM-based) implementation of the adachsoft/dynamic-table-contract package.
Provides complete CRUD for tables and rows, plus powerful querying capabilities (findBy()) with filtering, sorting, pagination, and column projection — all executed in memory without any external database.
Features
- Fully implements
TableRepositoryInterface and QueryableRowRepositoryInterface
- Isolated in-memory store (no static state, multiple independent instances supported)
- Efficient query engine with:
- Complex filters (
AND/OR/NOT, comparisons, LIKE, IN, null checks)
- Multi-level sorting (ASC/DESC)
- Pagination with accurate
totalCount
- Projection/aliasing with expressions (
CONCAT, TEMPLATE, JSON_EXTRACT, literals)
- Zero dependencies beyond the contract and PHP 8.2+
- Testable and lightweight
Installation
Add to your composer.json (in monorepo setup):
{
"repositories": [
{
"type": "path",
"url": "packages/dynamic-table-in-memory"
}
],
"require": {
"adachsoft/dynamic-table-in-memory": "*"
}
}
Then run:
composer install
Usage
Basic Setup
use AdachSoft\DynamicTableInMemory\Store\InMemoryStore;
use AdachSoft\DynamicTableInMemory\Repository\InMemoryTableRepository;
use AdachSoft\DynamicTableInMemory\Repository\InMemoryRowRepository;
use AdachSoft\DynamicTableInMemory\Query\ExpressionEvaluator;
use AdachSoft\DynamicTableInMemory\Query\FilterEvaluator;
use AdachSoft\DynamicTableInMemory\Query\RowProjector;
$store = new InMemoryStore();
$tableRepo = new InMemoryTableRepository($store);
$expressionEvaluator = new ExpressionEvaluator();
$filterEvaluator = new FilterEvaluator($expressionEvaluator);
$rowProjector = new RowProjector($expressionEvaluator);
$rowRepo = new InMemoryRowRepository(
$store,
$filterEvaluator,
$expressionEvaluator,
$rowProjector
);
Creating a Table
use AdachSoft\DynamicTableContract\Dto\NewTableDto;
use AdachSoft\DynamicTableContract\Dto\ColumnDto;
use AdachSoft\DynamicTableContract\Type\BuiltIn\StringType;
use AdachSoft\DynamicTableContract\Type\BuiltIn\IntType;
$columns = [
new ColumnDto('id', new IntType()),
new ColumnDto('name', new StringType()),
new ColumnDto('email', new StringType()),
];
$table = $tableRepo->create(new NewTableDto('users', $columns));
Row Operations
use AdachSoft\DynamicTableContract\Dto\NewRowDto;
$row = $rowRepo->add('users', null, new NewRowDto([
'name' => 'John Doe',
'email' => 'john@example.com',
]));
$retrieved = $rowRepo->getById('users', $row->id);
$rowRepo->update('users', $row->id, new NewRowDto([
'name' => 'Jane Doe',
'email' => 'jane@example.com',
]));
$rowRepo->delete('users', $row->id);
Advanced Querying with findBy()
use AdachSoft\DynamicTableContract\Query\Dto\QueryParametersDto;
use AdachSoft\DynamicTableContract\Query\Filter\EqualsCondition;
use AdachSoft\DynamicTableContract\Query\Filter\AndFilter;
use AdachSoft\DynamicTableContract\Query\Sort\SortVo;
use AdachSoft\DynamicTableContract\Query\Pagination\PaginationVo;
use AdachSoft\DynamicTableContract\Query\Expression\ConcatExpressionVo;
$filter = new AndFilter([
new LikeCondition::column('name', '%doe%'),
new IsNotNullCondition::column('email'),
]);
$sorts = new SortCollection([
SortVo::asc('name'),
SortVo::desc('email'),
]);
$params = new QueryParametersDto(
filter: $filter,
sorts: $sorts,
pagination: new PaginationVo(page: 1, perPage: 10),
selectedColumns: [
'full_name' => new ConcatExpressionVo(['name', 'email'], ' - '),
'email',
]
);
$result = $rowRepo->findBy('users', $params);
echo 'Total matching rows: ' . $result->totalCount . PHP_EOL;
foreach ($result->rows->all() as $row) {
echo $row->values['full_name'] . PHP_EOL;
}
See the contract documentation for full details on DTOs, expressions, filters, and types.
Testing
Run tests with:
cd packages/dynamic-table-in-memory
composer install
vendor/bin/phpunit
Or from root:
vendor/bin/phpunit --testsuite=InMemory
(All functional tests for both repositories are included in tests/Functional/.)
License
MIT License - see LICENSE file.
Contributing
See the main monorepo CONTRIBUTING.md.