PHPackages                             visorcraft/mongreldb-php - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. visorcraft/mongreldb-php

ActiveLibrary[Database &amp; ORM](/categories/database)

visorcraft/mongreldb-php
========================

Pure PHP client for MongrelDB - a fast embedded+server database with SQL, vector search, full-text search, and AI-native retrieval.

v0.2.1(3d ago)00MIT OR Apache-2.0PHP &gt;=8.4

Since Jul 8Compare

[ Source](https://github.com/visorcraft/MongrelDB-PHP)[ Packagist](https://packagist.org/packages/visorcraft/mongreldb-php)[ Docs](https://github.com/visorcraft/MongrelDB-PHP)[ RSS](/packages/visorcraft-mongreldb-php/feed)WikiDiscussions Synced today

READMEChangelogDependencies (1)Versions (3)Used By (0)

 [![MongrelDB logo](assets/mongrel.png)](assets/mongrel.png)

MongrelDB PHP Client
====================

[](#mongreldb-php-client)

 **Pure PHP client for MongrelDB - embedded+server database with SQL, vector search, full-text search, and AI-native retrieval.**

 [![Packagist](https://camo.githubusercontent.com/80588149351c1f91e05f382b9caa868f585e8693b701624bd919b16fb224ec05/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7669736f7263726166742f6d6f6e6772656c64622d7068702e737667)](https://packagist.org/packages/visorcraft/mongreldb-php) [![PHP](https://camo.githubusercontent.com/5d9d5c803630361612858a62f6ab4b428b6ce2d97efc901c575e54c76cb4df5f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d253345253344382e342d3737376262342e737667)](https://www.php.net/) [![License](https://camo.githubusercontent.com/6a380a6e924e76196bdb305d9a425347f5c103a5dfd60ae3b2722cd075777220/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542532304f522532304170616368652d2d322e302d626c75652e737667)](#license)

Package
-------

[](#package)

SurfacePackageInstallPHP client`visorcraft/mongreldb-php``composer require visorcraft/mongreldb-php`Requirements
------------

[](#requirements)

- **PHP 8.4 or newer** (PHP 8.5 supported with opt-in performance features)
- **ext-curl** (default HTTP transport) and **ext-json** (always required)
- A running [`mongreldb-server`](https://github.com/visorcraft/MongrelDB) daemon

What It Provides
----------------

[](#what-it-provides)

- **Typed CRUD** over the Kit transaction endpoint: `put`, `upsert` (insert-or-update on PK conflict), `delete` by row id or primary key, with idempotency keys for safe retries.
- **Fluent query builder** that pushes conditions down to the engine's specialized indexes for sub-millisecond lookups: bitmap equality/IN, learned-range, null checks, FM-index full-text search, HNSW vector similarity (`ann`), and sparse vector match.
- **Idempotent batch transactions** - all operations staged locally and committed atomically, with the engine enforcing unique, foreign key, and check constraints at commit time. Idempotency keys return the original response on duplicate commits, even after a crash.
- **Full SQL access** through the DataFusion-backed `/sql` endpoint: recursive CTEs, window functions, `CREATE TABLE AS SELECT`, materialized views, multi-statement execution, and the `mongreldb_fts_rank` relevance-scoring UDF.
- **Schema management**: typed table creation, full schema catalog, and per-table descriptors.
- **User/role/credentials management**: Argon2id-hashed catalog users, roles, `GRANT`/`REVOKE` table-level permissions, daemon HTTP Basic + Bearer auth, and a client-side permission validator that blocks SQL injection in grant strings.
- **Stored procedures**: install, list, drop, and call with typed arguments.
- **Maintenance**: compaction (all tables or per-table).
- **Pluggable HTTP transport**: cURL by default (with keep-alive connection pooling), a stream-based fallback, and a `TransportInterface` for custom adapters (e.g. a Guzzle/PSR-18 bridge).
- **Typed exception hierarchy**: `AuthException` (401/403), `NotFoundException` (404), `ConstraintException` (409, with error code + op index), `ConnectionException` (network), and `QueryException` (everything else).
- **Robust JSON handling**: malformed UTF-8 is substituted rather than rejecting the whole request; INF/NAN and recursive structures raise a clear `QueryException` instead of corrupting data.

Examples
--------

[](#examples)

Runnable, commented examples live in [`examples/`](examples):

- [Basic CRUD](examples/basic_crud.php) - connect, create a table, insert, query, count.
- [Authentication](examples/auth_example.php) - users, roles, table-level permissions, credential verification.
- [Transactions](examples/transactions.php) - batch commits, idempotency keys, constraint handling.
- [SQL queries](examples/sql_queries.php) - recursive CTEs, window functions, advanced SQL.

Quick Example
-------------

[](#quick-example)

```
use Visorcraft\MongrelDB\Database;

// Connect to a running mongreldb-server daemon
$db = new Database('http://127.0.0.1:8453');

// Create a table with an enum column, a regex CHECK, and a server-side default
$db->getClient()->post('/kit/create_table', [
    'name' => 'orders',
    'columns' => [
        ['id' => 1, 'name' => 'id',             'ty' => 'int64',           'primary_key' => true,  'nullable' => false],
        ['id' => 2, 'name' => 'customer_email', 'ty' => 'varchar',         'primary_key' => false, 'nullable' => false],
        ['id' => 3, 'name' => 'amount',         'ty' => 'float64',         'primary_key' => false, 'nullable' => false],
        ['id' => 4, 'name' => 'status',         'ty' => 'enum',            'primary_key' => false, 'nullable' => false,
         'enum_variants' => ['new', 'paid', 'cancelled']],
        ['id' => 5, 'name' => 'created_at',     'ty' => 'timestamp_nanos', 'primary_key' => false, 'nullable' => false,
         'default_value' => 'now'],
    ],
    'constraints' => [
        'checks' => [[
            'id' => 1,
            'name' => 'ck_customer_email',
            'expr' => ['Regex' => [
                'col' => 2,
                'pattern' => '^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$',
                'negated' => false,
                'case_insensitive' => true,
            ]],
        ]],
    ],
]);

// Insert rows; created_at is filled by the default_value above
$db->put('orders', [1 => 1, 2 => 'alice@example.com', 3 => 99.50,  4 => 'new']);
$db->put('orders', [1 => 2, 2 => 'bob@example.com',   3 => 150.00, 4 => 'paid']);

// Upsert (insert or update on PK conflict)
$db->upsert('orders', [1 => 1, 2 => 'alice@example.com', 3 => 120.00, 4 => 'paid'], updateCells: [3 => 120.00, 4 => 'paid']);

// Query with a native index condition (learned-range index)
$rows = $db->query('orders')
    ->where('range', ['column' => 3, 'min' => 100.0])
    ->projection([1, 2, 4])
    ->limit(100)
    ->execute();

echo $db->count('orders'); // 2

// Run SQL
$db->sql("UPDATE orders SET amount = 200.0 WHERE customer_email = 'bob@example.com'");
```

Authentication
--------------

[](#authentication)

```
// Bearer token (--auth-token mode)
$db = new Database('http://127.0.0.1:8453', token: 'my-secret-token');

// HTTP Basic (--auth-users mode)
$db = new Database('http://127.0.0.1:8453', username: 'admin', password: 's3cret');
```

Batch transactions
------------------

[](#batch-transactions)

Operations are staged locally and committed atomically. The engine enforces unique, foreign key, and check constraints at commit time.

```
$txn = $db->beginTransaction();
$txn->put('orders', [1 => 10, 2 => 'Dave', 3 => 50.00]);
$txn->put('orders', [1 => 11, 2 => 'Eve',  3 => 75.00]);
$txn->deleteByPk('orders', 2);

try {
    $txn->commit();                       // atomic - all or nothing
    echo "Staged {$txn->count()} operations\n";
} catch (\Visorcraft\MongrelDB\Exceptions\ConstraintException $e) {
    echo "Constraint violated: {$e->errorCode} - {$e->getMessage()}\n";
    $txn->rollback();
}

// Idempotent commit - safe to retry; daemon returns the original response
$txn = $db->beginTransaction();
$txn->put('orders', [1 => 20, 2 => 'Frank', 3 => 100.00]);
$txn->commit(idempotencyKey: 'order-20-create');
```

Native query builder
--------------------

[](#native-query-builder)

Conditions push down to the engine's specialized indexes. The builder accepts friendly aliases that are translated to the server's on-wire keys: `column`(-&gt; `column_id`), `min`/`max` (-&gt; `lo`/`hi`). The canonical keys are also accepted directly.

```
// Bitmap equality (low-cardinality columns)
$db->query('orders')->where('bitmap_eq', ['column' => 2, 'value' => 'Alice'])->execute();

// Range query (learned-range index)
$db->query('orders')
    ->where('range', ['column' => 3, 'min' => 50.0, 'max' => 150.0])
    ->limit(100)->execute();

// Full-text search (FM-index)
$db->query('documents')
    ->where('fm_contains', ['column' => 2, 'pattern' => 'database performance'])
    ->limit(10)->execute();

// Vector similarity search (HNSW)
$db->query('embeddings')
    ->where('ann', ['column' => 2, 'query' => [0.1, 0.2, 0.3], 'k' => 10])
    ->execute();

// Check whether a result was capped by the limit
$query = $db->query('orders')->where('range', ['column' => 3, 'min' => 0])->limit(100);
$rows = $query->execute();
if ($query->truncated()) {
    // result set hit the limit; more matches exist on the server
}
```

SQL
---

[](#sql)

```
$db->sql("INSERT INTO orders (id, customer, amount) VALUES (99, 'Zoe', 999.0)");
$db->sql("CREATE TABLE archive AS SELECT * FROM orders WHERE amount > 500");

// Recursive CTEs and window functions
$db->sql("WITH RECURSIVE r(n) AS (SELECT 1 UNION ALL SELECT n+1 FROM r WHERE nerrorCode}\n";          // UNIQUE_VIOLATION
} catch (Exceptions\AuthException $e) {
    echo "Not authorized: {$e->getMessage()}\n";
} catch (Exceptions\NotFoundException $e) {
    echo "Not found: {$e->getMessage()}\n";
} catch (Exceptions\ConnectionException $e) {
    echo "Can't reach daemon: {$e->getMessage()}\n";
} catch (Exceptions\MongrelDBException $e) {
    echo "Error: {$e->getMessage()}\n";
}
```

Enum-domain failures and regex/check-constraint failures are reported by the server as `ConstraintException` with `$e->errorCode === 'CHECK_VIOLATION'`.

API reference
-------------

[](#api-reference)

### `Database` class

[](#database-class)

MethodDescription`health(): bool`Check daemon health`tables(): array`List table names`createTable(string $name, array $columns): int`Create a table`dropTable(string $name): void`Drop a table`count(string $table): int`Row count`put(string $table, array $cells, ?string $key): array`Insert a row`upsert(string $table, array $cells, ?array $update, ?string $key): array`Upsert a row`delete(string $table, int $rowId): void`Delete by row ID`deleteByPk(string $table, mixed $pk): void`Delete by primary key`query(string $table): QueryBuilder`Start a native query`sql(string $sql): array`Execute SQL`schema(): array`Full schema catalog`schemaFor(string $table): array`Single table schema`createUser(string $user, string $pw): void`Create a user`dropUser(string $user): void`Drop a user`alterPassword(string $user, string $pw): void`Change a password`verifyUser(string $user, string $pw): bool`Verify credentials`setUserAdmin(string $user, bool $isAdmin): void`Grant/revoke admin`users(): array`List usernames`createRole(string $name): void`Create a role`dropRole(string $name): void`Drop a role`roles(): array`List role names`grantRole(string $user, string $role): void`Grant role to user`revokeRole(string $user, string $role): void`Revoke role from user`grantPermission(string $role, string $perm): void`Grant permission`revokePermission(string $role, string $perm): void`Revoke permission`procedures(): array`List procedures`procedure(string $name): array`Get a procedure`createProcedure(array $proc): array`Install/replace a procedure`dropProcedure(string $name): void`Drop a procedure`callProcedure(string $name, array $args): mixed`Call a procedure`compact(): array`Compact all tables`compactTable(string $name): array`Compact one table`beginTransaction(): Transaction`Start a batch`createTable()` forwards each column array unchanged in the `columns` payload. Column specs accept the standard keys (`id`, `name`, `ty`, `primary_key`, `nullable`, `auto_increment`, `encrypted`, `encrypted_indexable`) plus:

Column keyDescription`enum_variants`String variants for `ty => 'enum'`; required and non-empty for enum columns`default_value`Server default expression string, such as `now` for `timestamp_nanos`/`varchar` or `uuid` for `varchar`; the daemon also accepts `default_expr`Table-level check constraints are sent on the raw Kit create-table payload under `constraints.checks`:

```
$db->getClient()->post('/kit/create_table', [
    'name' => 'orders',
    'columns' => $columns,
    'constraints' => [
        'checks' => [[
            'id' => 1,
            'name' => 'ck_email',
            'expr' => ['Regex' => [
                'col' => 2,
                'pattern' => '^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$',
                'negated' => false,
                'case_insensitive' => true,
            ]],
        ]],
    ],
]);
```

### `QueryBuilder` class

[](#querybuilder-class)

MethodDescription`where(string $type, array $params): static`Add a native condition`projection(array $columnIds): static`Set column projection`limit(int $limit): static`Set row limit`build(): array`Build the request payload`execute(): array`Run the query### `Transaction` class

[](#transaction-class)

MethodDescription`put(string $table, array $cells): static`Stage an insert`upsert(string $table, array $cells, ?array $update): static`Stage an upsert`delete(string $table, int $rowId): static`Stage a delete`deleteByPk(string $table, mixed $pk): static`Stage a delete by PK`commit(?string $key): array`Commit atomically`rollback(): void`Discard all operations`count(): int`Number of staged operationsBuilding and testing
--------------------

[](#building-and-testing)

The test suite uses PHPUnit 12 and is fully offline - it does **not** require a running daemon (a mock transport intercepts all HTTP calls).

```
composer install
composer test              # runs the full suite
vendor/bin/phpunit         # equivalent
```

The suite covers 273 tests across SQL-injection hardening, JSON edge cases (INF/NAN, malformed UTF-8, recursion), transport behavior, transaction state machines, and the optional persistent-sharing feature.

Contributing
------------

[](#contributing)

Contributions are welcome. Please:

1. Open an issue first for non-trivial changes.
2. Add focused tests near your change - the suite must stay green.
3. Keep PHP 8.4 as the minimum supported version (PHP 8.5-only features must degrade gracefully, detected at runtime via `function_exists`/`defined`).
4. Match the existing style: strict types, `declare(strict_types=1)`, tabs, `readonly` properties where applicable, and `#[\Override]` on overridden methods.

License
-------

[](#license)

Dual-licensed under the **MIT License** or the **Apache License, Version 2.0**, at your option. See [MIT](LICENSE-MIT) OR [Apache-2.0](LICENSE-APACHE) for the full text.

`SPDX-License-Identifier: MIT OR Apache-2.0`

###  Health Score

38

—

LowBetter than 83% of packages

Maintenance99

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity42

Maturing project, gaining track record

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

2

Last Release

3d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/346abc053d68ccb92059756fb86be6c2c7f07dea343d21e4bf4177c32f22d6e9?d=identicon)[VisorCraft](/maintainers/VisorCraft)

---

Tags

searchdatabaseaisqlvectorembeddedmongreldb

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/visorcraft-mongreldb-php/health.svg)

```
[![Health](https://phpackages.com/badges/visorcraft-mongreldb-php/health.svg)](https://phpackages.com/packages/visorcraft-mongreldb-php)
```

###  Alternatives

[foolz/sphinxql-query-builder

A PHP query builder for SphinxQL and ManticoreQL with MySQLi and PDO drivers.

3232.2M34](/packages/foolz-sphinxql-query-builder)[rah/danpu

Zero-dependency MySQL dump library for easily exporting and importing databases

62414.3k11](/packages/rah-danpu)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
