PHPackages                             herdianrony/bangrondb - 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. herdianrony/bangrondb

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

herdianrony/bangrondb
=====================

SQLite-based NoSQL document database with MongoDB-like API, encryption, hooks, relationships, and enterprise features

v1.2.0(6d ago)0418MITPHPPHP ^8.1

Since Jun 20Pushed 3w agoCompare

[ Source](https://github.com/herdianrony/BangronDB)[ Packagist](https://packagist.org/packages/herdianrony/bangrondb)[ Docs](https://github.com/herdianrony/BangronDB)[ RSS](/packages/herdianrony-bangrondb/feed)WikiDiscussions master Synced today

READMEChangelogDependencies (4)Versions (5)Used By (0)

BangronDB
=========

[](#bangrondb)

BangronDB adalah database dokumen berbasis SQLite untuk PHP dengan API bergaya MongoDB. Library ini cocok untuk aplikasi kecil hingga menengah yang membutuhkan penyimpanan lokal, query fleksibel, enkripsi, hooks, schema validation, dan relasi sederhana tanpa harus menjalankan server database terpisah.

[![License](https://camo.githubusercontent.com/8bb50fd2278f18fc326bf71f6e88ca8f884f72f179d3e555e20ed30157190d0d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d677265656e2e737667)](LICENSE)[![PHP](https://camo.githubusercontent.com/3a551e6c37f4d5451a70062155ccea8dec2f6eb8a55eb1a1410a5166fce4b020/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d253345253344253230382e312d626c75652e737667)](https://www.php.net)

Sorotan Fitur
-------------

[](#sorotan-fitur)

- API mirip MongoDB untuk operasi dokumen
- Backend SQLite berbasis file atau in-memory
- Enkripsi dokumen dengan **AES-256-GCM**
- Searchable fields untuk data terenkripsi
- Hooks untuk lifecycle insert, update, dan remove
- Schema validation untuk type, enum, regex, min/max
- Soft delete dengan restore dan force delete
- ID mode fleksibel: UUID, manual, prefix
- Populate relasi antar-collection dan antar-database dalam satu client
- Health metrics, integrity check, dan change notification
- Konfigurasi collection yang bisa disimpan ke database

Kebutuhan Sistem
----------------

[](#kebutuhan-sistem)

- PHP **8.1+**
- Ekstensi `pdo_sqlite`
- Ekstensi `openssl`
- Composer

Instalasi
---------

[](#instalasi)

```
composer require herdianrony/bangrondb
```

Quick Start
-----------

[](#quick-start)

```
use BangronDB\Client;

$client = new Client(__DIR__ . '/data');
$client->createDB('app');
$client->createCollection('app', 'users');

$users = $client->selectCollection('app', 'users');

// Insert
$userId = $users->insert([
    'name' => 'John Doe',
    'email' => 'john@example.com',
    'role' => 'admin',
]);

// Find
$user = $users->findOne(['_id' => $userId]);

echo $user['name'] . PHP_EOL;

// Update
$users->update(['_id' => $userId], [
    '$set' => ['role' => 'superadmin'],
]);

// Delete
$users->remove(['_id' => $userId]);
```

Konsep Dasar
------------

[](#konsep-dasar)

```
Client -> Database (.bangron / :memory:) -> Collection -> Document

```

- **Client** mengelola banyak database dalam satu path.
- **Database** mewakili satu file SQLite/BangronDB.
- **Collection** mewakili tabel dokumen.
- **Document** disimpan sebagai JSON.

Membuat Client dan Database
---------------------------

[](#membuat-client-dan-database)

```
use BangronDB\Client;

// File-based storage
$client = new Client(__DIR__ . '/data');

// In-memory
$memoryClient = new Client(':memory:');

// Dengan opsi runtime
$secureClient = new Client(__DIR__ . '/data', [
    'encryption_key' => $_ENV['DB_ENCRYPTION_KEY'] ?? null,
    'query_logging' => false,
    'performance_monitoring' => false,
]);

// API eksplisit untuk lifecycle database
$client->createDB('app');
$client->dbExists('app'); // true

$db = $client->selectDB('app');
$db = $client->app; // magic getter, untuk database yang sudah ada

$client->createCollection('app', 'users');
$client->collectionExists('app', 'users'); // true
$client->listCollections('app');           // ['users', ...] (alias: listCollection)

$users = $client->selectCollection('app', 'users');
$users = $db->users; // magic getter, untuk collection yang sudah ada

$client->renameCollection('app', 'users', 'members');
$client->dropCollection('app', 'members');

// Atau dari object Database jika lebih nyaman
$db->createCollection('logs');
$db->collectionExists('logs'); // true

// Rename / hapus database
$client->renameDB('app', 'app_v2');
$client->dropDB('app_v2');

$client->close();
```

> Mulai versi ini, `selectDB()` dan `selectCollection()` bersifat **non-lazy**: keduanya hanya memilih resource yang sudah ada.
>
> Untuk membuat resource baru secara eksplisit, gunakan:
>
> - `createDB()` untuk database
> - `createCollection()` untuk collection

CRUD
----

[](#crud)

### Insert

[](#insert)

```
$id = $users->insert([
    'name' => 'Alice',
    'email' => 'alice@example.com',
]);

$count = $users->insert([
    ['name' => 'Bob'],
    ['name' => 'Charlie'],
]);
```

### Find

[](#find)

```
$all = $users->find()->toArray();
$one = $users->findOne(['name' => 'Alice']);

$activeAdults = $users->find([
    'status' => 'active',
    'age' => ['$gte' => 21],
])->toArray();

$projection = $users->find(
    ['status' => 'active'],
    ['name' => 1, 'email' => 1]
)->toArray();

$total = $users->count(['status' => 'active']);
```

### Update

[](#update)

```
// Merge update (default)
$users->update(['name' => 'Alice'], ['city' => 'Jakarta']);

// Replace update
$users->update(['name' => 'Alice'], ['name' => 'Alice', 'city' => 'Bandung'], false);

// Operator-style update
$users->update(['name' => 'Alice'], [
    '$set' => ['role' => 'editor'],
    '$unset' => ['legacy_field' => ''],
]);
```

### Save / Upsert

[](#save--upsert)

```
// Tanpa _id => insert baru
$newId = $users->save(['name' => 'Dina']);

// Dengan _id => update jika sudah ada, insert jika belum ada
$users->save([
    '_id' => 'USR-000001',
    'name' => 'Dina Updated',
]);
```

### Delete

[](#delete)

```
$deleted = $users->remove(['status' => 'inactive']);
$users->remove([]); // hapus semua dokumen
```

Pagination, Sorting, Projection
-------------------------------

[](#pagination-sorting-projection)

```
$results = $users->find(['status' => 'active'])
    ->sort(['age' => 1])
    ->skip(10)
    ->limit(5)
    ->toArray();
```

Query Operators
---------------

[](#query-operators)

### Comparison

[](#comparison)

```
$users->find(['age' => ['$gt' => 18]]);
$users->find(['age' => ['$gte' => 21]]);
$users->find(['age' => ['$lt' => 65]]);
$users->find(['age' => ['$lte' => 60]]);
$users->find(['age' => ['$ne' => 30]]);
```

### Array / Membership

[](#array--membership)

```
$users->find(['role' => ['$in' => ['admin', 'editor']]]);
$users->find(['role' => ['$nin' => ['guest', 'banned']]]);
$users->find(['tags' => ['$all' => ['php', 'sqlite']]]);
$users->find(['tags' => ['$size' => 3]]);
```

### Existence dan Logical

[](#existence-dan-logical)

```
$users->find(['email' => ['$exists' => true]]);

$users->find(['$or' => [
    ['age' => ['$lt' => 18]],
    ['age' => ['$gt' => 65]],
]]);

$users->find(['$and' => [
    ['status' => 'active'],
    ['age' => ['$gte' => 21]],
]]);
```

### Regex, Closure, Fuzzy Search, Dot Notation

[](#regex-closure-fuzzy-search-dot-notation)

```
$users->find(['name' => ['$regex' => '^John']]);

$users->find(['age' => ['$where' => fn($doc) => $doc['age'] > 18]]);
$users->find(['name' => ['$func' => fn($val) => strlen($val) > 5]]);

$users->find([
    'description' => [
        '$fuzzy' => [
            '$search' => 'important',
            '$minScore' => 0.7,
        ],
    ],
]);

$users->find(['address.city' => 'Jakarta']);
```

> `'$where'` dan `'$func'` hanya menerima **Closure**, bukan string function name.

Enkripsi
--------

[](#enkripsi)

### Database-level encryption

[](#database-level-encryption)

```
use BangronDB\Database;

$db = new Database(__DIR__ . '/secure.bangron', [
    'encryption_key' => $_ENV['DB_ENCRYPTION_KEY'],
]);
```

### Collection-level encryption

[](#collection-level-encryption)

```
$users->setEncryptionKey($_ENV['DB_ENCRYPTION_KEY']);

$users->insert([
    'name' => 'Alice',
    'ssn' => '123-45-6789',
]);
```

### Searchable fields untuk data terenkripsi

[](#searchable-fields-untuk-data-terenkripsi)

```
$users->setEncryptionKey($_ENV['DB_ENCRYPTION_KEY']);
$users->setSearchableFields(['email', 'phone'], true); // true = SHA-256 hash
$users->saveConfiguration();
```

**Catatan teknis:** BangronDB menggunakan **AES-256-GCM**, key derivation berbasis PBKDF2 SHA-256, IV acak per enkripsi, dan payload Base64 di dokumen JSON.

Schema Validation
-----------------

[](#schema-validation)

```
$users->setSchema([
    'username' => ['required' => true, 'type' => 'string', 'min' => 3, 'max' => 50],
    'email'    => ['required' => true, 'type' => 'string', 'unique' => true, 'regex' => '/^[^\s@]+@[^\s@]+\.[^\s@]+$/'],
    'age'      => ['type' => 'int', 'min' => 13, 'max' => 120],
    'role'     => ['type' => 'string', 'enum' => ['admin', 'user', 'moderator']],
]);

$users->validate([
    'username' => 'john',
    'email' => 'john@example.com',
]);
```

> Validasi `enum` menggunakan strict comparison. Misalnya, nilai `0`, `false`, dan `'0'` dianggap berbeda.

### Unique constraint

[](#unique-constraint)

Tandai sebuah field dengan `'unique' => true` agar BangronDB menolak dokumen baru (atau update) yang nilainya sudah ada di koleksi. Pengecekan dijalankan otomatis saat `insert()` / `update()` dan melempar `ValidationException`(`UNIQUE_CONSTRAINT_VIOLATION`). Nilai `null` tidak dikenai constraint, dan update pada dokumen yang sama (nilai tidak berubah) tidak dianggap duplikat.

```
$users->setSchema(['email' => ['type' => 'string', 'unique' => true]]);
$users->insert(['email' => 'a@example.com']);
$users->insert(['email' => 'a@example.com']); // throws ValidationException
```

> Catatan untuk field **terenkripsi**: pengecekan unik memakai query equality, sehingga pada koleksi terenkripsi field tersebut harus juga dijadikan **searchable** (`setSearchableFields([... => ['hash' => true]])`) agar nilai dapat dicari lewat blind index. Tanpa itu, dokumen terenkripsi tidak bisa di-query per-nilai dan constraint tidak akan menemukan duplikat.

Soft Deletes
------------

[](#soft-deletes)

```
$users->useSoftDeletes(true);

$users->remove(['username' => 'johndoe']);
$users->find()->withTrashed()->toArray();
$users->find()->onlyTrashed()->toArray();
$users->restore(['username' => 'johndoe']);
$users->forceDelete(['username' => 'johndoe']);
```

Hooks
-----

[](#hooks)

```
$users->on('beforeInsert', function ($document) {
    $document['created_at'] = date('c');
    return $document;
});

$users->on('afterInsert', function ($document, $insertId) {
    error_log('Inserted: ' . $insertId);
});

$users->on('beforeUpdate', function ($criteria, $data) {
    $data['updated_at'] = date('c');
    return ['criteria' => $criteria, 'data' => $data];
});

$users->on('beforeRemove', function ($document) {
    if ($document['protected'] ?? false) {
        return false;
    }
});
```

Event yang tersedia:

- `beforeInsert`
- `afterInsert`
- `beforeUpdate`
- `afterUpdate`
- `beforeRemove`
- `afterRemove`

Relationships / Populate
------------------------

[](#relationships--populate)

```
$posts = $db->posts->find()
    ->populate('author_id', $db->users, ['as' => 'author'])
    ->toArray();

$post = $db->posts->populate($post, 'comment_ids', 'app.comments', '_id', 'comments');
```

Indexing
--------

[](#indexing)

```
$users->createIndex('email');
$users->createIndex('address.city');
$users->createIndex('status', 'idx_status');

$db->dropIndex('idx_status');
```

Health &amp; Monitoring
-----------------------

[](#health--monitoring)

```
$health = $db->getHealthMetrics();
$report = $db->getHealthReport();
$perf   = $db->getPerformanceMetrics();
$index  = $db->getIndexMetrics();
$coll   = $db->getCollectionMetrics();

$db->checkIntegrity();
$db->vacuum();
```

Change Notification
-------------------

[](#change-notification)

```
$lastModified = $users->getLastModified();
// ['version' => 42, 'last_updated' => '2026-06-20T10:30:45+07:00']

$users->notifyChange();
```

Dynamic Configuration
---------------------

[](#dynamic-configuration)

Konfigurasi collection berikut bisa disimpan ke database:

- ID mode
- searchable fields
- schema
- soft deletes
- custom config

```
$users->setIdModePrefix('USR');
$users->setSearchableFields(['email'], true);
$users->setSchema([...]);
$users->useSoftDeletes(true);
$users->saveConfiguration();
```

> Encryption key **tidak disimpan** di database. Selalu supply dari `.env`, secret manager, atau runtime config.
>
> Catatan: konfigurasi ID prefix yang dipersist kini dinormalisasi ke format `prefix:USR`. Konfigurasi lama yang masih menyimpan prefix mentah seperti `USR` tetap didukung saat dibaca ulang.

Transactions
------------

[](#transactions)

BangronDB menggunakan PDO SQLite di bawahnya, jadi Anda bisa memakai transaksi langsung lewat koneksi PDO:

```
$db->connection->beginTransaction();

try {
    $db->users->insert(['name' => 'Alice']);
    $db->profiles->insert(['user' => 'Alice']);
    $db->connection->commit();
} catch (\Throwable $e) {
    $db->connection->rollBack();
    throw $e;
}
```

Keamanan
--------

[](#keamanan)

BangronDB menerapkan beberapa guardrail penting:

FiturTujuanClosure-only untuk `$where` / `$func`Mencegah RCEValidasi field nameMencegah injectionPRAGMA key escapingMencegah SQLite injectionRegex hardeningMengurangi risiko ReDoSValidasi pathMengurangi risiko path traversal`strict_types=1`Type safetyLihat juga [SECURITY\_USAGE\_GUIDE.md](SECURITY_USAGE_GUIDE.md).

API Ringkas
-----------

[](#api-ringkas)

### Client

[](#client)

MethodKeterangan`new Client($path, $options = [])`Membuat client`createDB($name, $options = [])`Membuat database secara eksplisit`dbExists($name)`Mengecek apakah database ada`listDBs()`Daftar database`selectDB($name)`Ambil database`renameDB($oldName, $newName)`Rename database`dropDB($name)`Hapus database`createCollection($db, $collection)`Membuat collection langsung dari level client`collectionExists($db, $collection)`Mengecek collection dari level client`listCollections($db)` / `listCollection($db)`Daftar nama collection di sebuah database (`[]` jika DB tidak ada)`renameCollection($db, $oldName, $newName)`Rename collection dari level client`dropCollection($db, $collection)`Hapus collection dari level client`selectCollection($db, $collection)`Ambil collection langsung`close()`Tutup koneksi### Database

[](#database)

MethodKeterangan`selectCollection($name)`Ambil collection`createCollection($name)`Buat collection`collectionExists($name)`Mengecek apakah collection ada`renameCollection($oldName, $newName)`Rename collection`dropCollection($name)`Hapus collection`getCollectionNames()`Daftar nama collection`createJsonIndex($collection, $field, $indexName = null)`Buat index JSON`dropIndex($indexName)`Hapus index`getHealthMetrics()`Ambil health metrics`getHealthReport()`Ambil health report`getPerformanceMetrics()`Ambil metrik performa`getCollectionMetrics()`Ambil metrik per collection`saveCollectionConfig($name, $config)`Simpan konfigurasi`loadCollectionConfig($name)`Muat konfigurasi`deleteCollectionConfig($name)`Hapus konfigurasi`checkIntegrity()`Jalankan integrity check`vacuum()`Optimasi file database### Collection

[](#collection)

MethodKeterangan`insert($document)`Insert satu/banyak dokumen`find($criteria = null, $projection = null)`Query dokumen`findOne($criteria = null, $projection = null)`Query satu dokumen`update($criteria, $data, $merge = true)`Update dokumen`remove($criteria)`Hapus dokumen`count($criteria = null)`Hitung dokumen`save($document)`Insert / upsert dokumen`drop()`Hapus collection`renameCollection($newName)`Rename collection`setIdModeAuto()` / `setIdModeManual()` / `setIdModePrefix($prefix)`Atur mode ID`setEncryptionKey($key)`Atur key enkripsi`setSearchableFields($fields, $hash = false)`Atur searchable fields`removeSearchableField($field, $dropColumn = false)`Hapus searchable field`setSchema($schema)`Atur schema`useSoftDeletes($enabled = true)`Aktifkan soft delete`restore($criteria)`Restore dokumen terhapus`forceDelete($criteria)`Hapus permanen`on($event, $callback)`Register hook`off($event, $callback = null)`Hapus hook`createIndex($field, $indexName = null)`Buat index`getLastModified()`Ambil metadata perubahan`notifyChange()`Trigger manual change notification`saveConfiguration()`Simpan konfigurasi collection### Cursor

[](#cursor)

MethodKeterangan`limit($n)`Batas hasil`skip($n)`Lewati hasil awal`sort($fields)`Urutkan hasil`populate($field, $collection, $options = [])`Populate relasi`withTrashed()`Sertakan soft-deleted`onlyTrashed()`Hanya soft-deleted`toArray()`Materialisasi ke array`toArraySafe($maxResults = null)`Materialisasi dengan batas aman`each($callback)`Iterasi tiap dokumenKonfigurasi Environment
-----------------------

[](#konfigurasi-environment)

Salin `.env.example` menjadi `.env` lalu isi sesuai kebutuhan:

```
DB_PATH=                         # Kosongkan untuk in-memory
ENCRYPTION_KEY=                  # Key kuat minimal 32 karakter
QUERY_LOGGING=false
PERFORMANCE_MONITORING=false
```

Contoh Lengkap
--------------

[](#contoh-lengkap)

Lihat folder [examples/](examples/) untuk contoh end-to-end:

- `01-quick-start-crud.php`
- `02-query-operators.php`
- `03-encryption-searchable.php`
- `04-schema-validation.php`
- `05-soft-deletes.php`
- `06-hooks.php`
- `07-relationships-populate.php`
- `08-transactions.php`
- `09-indexing-health-monitoring.php`
- `10-dynamic-configuration.php`
- `11-multiple-databases.php`
- `12-id-modes-collection-management.php`
- `13-security-features.php`
- `14-ecommerce-app.php`
- `15-auth-encrypted.php`

Catatan Kompatibilitas
----------------------

[](#catatan-kompatibilitas)

Jika Anda bermigrasi dari perilaku lama yang mengandalkan create implicit saat `selectDB()` / `selectCollection()`, lihat:

- [BACKWARD\_COMPATIBILITY\_NOTES.md](BACKWARD_COMPATIBILITY_NOTES.md)

Kontribusi
----------

[](#kontribusi)

Lihat [CONTRIBUTING.md](CONTRIBUTING.md).

Lisensi
-------

[](#lisensi)

BangronDB dilisensikan dengan [MIT](LICENSE).

###  Health Score

44

—

FairBetter than 90% of packages

Maintenance97

Actively maintained with recent releases

Popularity18

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity45

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

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 ~32 days

Total

4

Last Release

6d ago

PHP version history (2 changes)v1.0.1PHP &gt;=8.0

v1.0.0PHP ^8.1

### Community

Maintainers

![](https://www.gravatar.com/avatar/39bc178d58ce72cadd3a4d1d51f20f9faf82ef707541ff054a39dad7e4b2302c?d=identicon)[herdianrony](/maintainers/herdianrony)

---

Top Contributors

[![herdianrony](https://avatars.githubusercontent.com/u/31861521?v=4)](https://github.com/herdianrony "herdianrony (22 commits)")

---

Tags

jsonencryptiondatabasesqlitenosqlmongodbphp8php-databaseembedded-databasedocument-databaselightweight-database

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/herdianrony-bangrondb/health.svg)

```
[![Health](https://phpackages.com/badges/herdianrony-bangrondb/health.svg)](https://phpackages.com/packages/herdianrony-bangrondb)
```

###  Alternatives

[scienta/doctrine-json-functions

A set of extensions to Doctrine that add support for json query functions.

58825.9M53](/packages/scienta-doctrine-json-functions)[apix/cache

A thin PSR-6 cache wrapper with a generic interface to various caching backends emphasising cache taggging and indexing to Redis, Memcached, PDO/SQL, APC and other adapters.

117548.2k6](/packages/apix-cache)[tommyknocker/pdo-database-class

Framework-agnostic PHP database library with unified API for MySQL, MariaDB, PostgreSQL, SQLite, MSSQL, and Oracle. Query Builder, caching, sharding, window functions, CTEs, JSON, migrations, ActiveRecord, CLI tools, AI-powered analysis. Zero external dependencies.

846.1k](/packages/tommyknocker-pdo-database-class)[moharrum/laravel-adminer

Adminer database management tool for your Laravel application.

451.0k](/packages/moharrum-laravel-adminer)

PHPackages © 2026

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