herdianrony/bangrondb
Composer 安装命令:
composer require herdianrony/bangrondb
包简介
SQLite-based NoSQL document database with MongoDB-like API, encryption, hooks, relationships, and enterprise features
关键字:
README 文档
README
Saya bikin BangronDB karena di project-project saya (ERP, CRM, POS, HRIS) saya berulang kali butuh hal yang sama: database dokumen yang fleksibel, bisa di-deploy tanpa setup server, dan punya API yang enak dipakai. MongoDB-style API di atas SQLite adalah jawaban saya.
Library ini cocok untuk aplikasi yang di-deploy per-customer (appliance model), embedded di sistem existing, atau project SMB yang tidak butuh PostgreSQL/MySQL. Bukan untuk SaaS multi-tenant skala besar — gunakan PostgreSQL + RLS untuk itu.
Sorotan Fitur
- API mirip MongoDB untuk operasi dokumen
- Backend SQLite berbasis file atau in-memory
- Dual query strategy: SQL-first via
json_extract, fallback ke PHP-sideUtilArrayQueryuntuk query kompleks - Enkripsi dokumen dengan AES-256-GCM + key rotation (v1.2.0)
- Searchable fields (blind index SHA-256) untuk query pada data terenkripsi
- Hooks untuk lifecycle insert, update, dan remove
- Schema validation: type, enum/options, regex, min/max, unique constraint
- Aggregation pipeline:
$match,$group,$sort,$limit,$skip,$project,$count,$unset - Soft delete dengan restore dan force delete
- TTL (Time-To-Live) auto-expiration
- Cursor streaming via PHP Generator untuk efisiensi memori
- ID mode fleksibel: UUID, manual, prefix
- Populate relasi antar-collection dan antar-database
EXPLAINquery plan dan optimization suggestions- Health metrics, integrity check, dan change notification
- Konfigurasi collection yang persisten ke database
- Security auditor utilitas (opsional)
Arsitektur
Struktur Kode
src/
├── Client.php # Entry point: mengelola banyak database
├── Database.php # Satu file .bangron / :memory:
├── Collection.php # Tabel dokumen (menggunakan traits)
├── Cursor.php # Lazy query result iterator
├── QueryExecutor.php # Eksekusi SQL via PDO prepared statements
├── UtilArrayQuery.php # PHP-side query engine (fallback)
├── Config.php # Global configuration
├── Enums/ # Enum: HookEvent, IdMode
├── Exceptions/ # Typed exceptions
├── Security/ # SecurityAuditor (utilitas opsional)
└── Traits/ # Fitur-fitur collection (horizontal reuse)
├── QueryBuilderTrait.php
├── EncryptionTrait.php
├── SchemaValidationTrait.php
├── HooksTrait.php
├── SearchableFieldsTrait.php
├── IdGeneratorTrait.php
├── SoftDeleteTrait.php
├── TtlTrait.php
├── ChangeTrackingTrait.php
└── ConfigurationPersistenceTrait.php
Desain Trait-based
Collection menggunakan traits untuk horizontal code reuse — bukan inheritance. Setiap trait adalah unit tunggal yang fokus pada satu tanggung jawab:
| Trait | Tanggung Jawab |
|---|---|
QueryBuilderTrait |
Query logic, find(), findOne(), count(), operator parsing |
EncryptionTrait |
Enkripsi/dekripsi AES-256-GCM, key rotation |
SchemaValidationTrait |
Validasi type, enum, regex, min/max, unique |
HooksTrait |
Event lifecycle (before/after insert/update/remove) |
SearchableFieldsTrait |
Blind index untuk query pada data terenkripsi |
IdGeneratorTrait |
UUID, manual, prefix ID generation |
SoftDeleteTrait |
Soft delete, restore, force delete |
TtlTrait |
Auto-expiration dokumen berdasarkan TTL |
ChangeTrackingTrait |
Versioning dan change notification |
ConfigurationPersistenceTrait |
Simpan/muat konfigurasi collection ke database |
Pendekatan ini menjaga Collection.php tetap ringan sebagai koordinator, sementara logika detail tersebar di file terpisah yang bisa di-maintain secara independen.
Dual Query Strategy
BangronDB menggunakan dua lapis query secara otomatis:
Query masuk → _canTranslateToJsonWhere()?
├─ YA → _buildJsonWhere() → SQL WHERE via json_extract/->>/-> (cepat)
└─ TIDAK → fetch semua → UtilArrayQuery::match() di PHP (fleksibel)
- SQL-first: Query sederhana (equality, comparison,
$in, logical operators) diterjemahkan ke SQLWHERE json_extract(document, '$.field')dan dieksekusi langsung oleh SQLite engine. Ini memanfaatkan index dan meminimalkan data yang di-load ke PHP. - PHP fallback: Query kompleks (regex, closure/
$where, fuzzy search, dot notation nested) yang tidak bisa diterjemahkan ke SQL menggunakanUtilArrayQueryuntuk filtering di level PHP.
Strategi ini otomatis — pengguna tidak perlu memilih secara manual.
Yang BUKAN Bagian Core
Beberapa fitur yang sering dikira built-in sebenarnya adalah pola aplikasi yang didemonstrasikan di examples/, bukan bagian dari library:
- RBAC/ACL → Contoh 22, 23, 24: pola menggunakan
setCustomConfig()+ hooks untuk enforce permission di application layer - Change tracking audit log → Contoh di examples: pola menggunakan hooks untuk mencatat perubahan
- Authentication → Contoh 20: pola hashing password + hooks
BangronDB menyediakan primitif (hooks, schema, custom config) yang memungkinkan pola-pola ini dibangun di atasnya, tanpa memaksakan paradigma tertentu ke aplikasi pengguna.
Kebutuhan Sistem
- PHP 8.1+
- Ekstensi
pdo_sqlite - Ekstensi
openssl - Composer
Instalasi
composer require herdianrony/bangrondb
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
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
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()danselectCollection()bersifat non-lazy: keduanya hanya memilih resource yang sudah ada.Untuk membuat resource baru secara eksplisit, gunakan:
createDB()untuk databasecreateCollection()untuk collection
CRUD
Insert
$id = $users->insert([ 'name' => 'Alice', 'email' => 'alice@example.com', ]); $count = $users->insert([ ['name' => 'Bob'], ['name' => 'Charlie'], ]);
InsertMany / UpdateMany / DeleteMany (API MongoDB-compatible)
// InsertMany: insert batch dengan hasil detail $result = $users->insertMany([ ['name' => 'Alice', 'email' => 'alice@example.com'], ['name' => 'Bob', 'email' => 'bob@example.com'], ]); // ['inserted_count' => 2, 'inserted_ids' => ['...', '...']] // UpdateMany: update semua dokumen yang cocok $result = $users->updateMany(['status' => 'pending'], ['$set' => ['status' => 'active']]); // ['matched_count' => 5, 'modified_count' => 5] // DeleteMany $result = $users->deleteMany(['status' => 'banned']); // ['deleted_count' => 2]
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
// 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
// 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
$deleted = $users->remove(['status' => 'inactive']); $users->remove([]); // hapus semua dokumen
Pagination, Sorting, Projection
$results = $users->find(['status' => 'active']) ->sort(['age' => 1]) ->skip(10) ->limit(5) ->toArray();
Query Operators
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
$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
$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
$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.
Aggregation Pipeline
$results = $users->aggregate([ ['$match' => ['status' => 'active']], ['$group' => ['_id' => '$role', 'total' => ['$sum' => 1], 'avg_age' => ['$avg' => '$age']]], ['$sort' => ['total' => -1]], ['$limit' => 10], ]);
Operator yang didukung:
| Stage | Deskripsi |
|---|---|
$match |
Filter dokumen (sintaks sama seperti find()) |
$group |
Grouping dengan akumulator: $sum, $avg, $min, $max, $count, $first, $last, $push, $addToSet |
$sort |
Urutkan dokumen |
$limit |
Batasi jumlah hasil |
$skip |
Lewati N dokumen pertama |
$project |
Reshape dokumen (include/exclude field, field reference) |
$count |
Hitung dokumen yang lolos pipeline |
$unset |
Hapus field dari semua dokumen |
Field reference menggunakan prefix $: '$fieldName' merujuk ke nilai field dokumen.
Cursor Streaming
Untuk dataset besar, gunakan stream() yang menghasilkan Generator — memori tetap konstan terlepas dari ukuran hasil:
foreach ($users->stream(['status' => 'active'], [ 'sort' => ['created_at' => -1], 'limit' => 10000, ]) as $doc) { processDocument($doc); // hanya satu dokumen di memori }
Explain Query
Analisis bagaimana query dieksekusi — apakah menggunakan index, full scan, dan saran optimasi:
$explanation = $users->explain(['status' => 'active', 'age' => ['$gte' => 21]]); echo $explanation['query_plan']['uses_index'] ? 'Uses index' : 'Full scan'; echo "Scanned: {$explanation['performance']['documents_scanned']} documents"; echo "Time: {$explanation['performance']['execution_time_ms']}ms"; foreach ($explanation['suggestions'] as $suggestion) { echo "Suggestion: {$suggestion}"; }
Enkripsi
Database-level encryption
use BangronDB\Database; $db = new Database(__DIR__ . '/secure.bangron', [ 'encryption_key' => $_ENV['DB_ENCRYPTION_KEY'], ]);
Collection-level encryption
$users->setEncryptionKey($_ENV['DB_ENCRYPTION_KEY']); $users->insert([ 'name' => 'Alice', 'ssn' => '123-45-6789', ]);
Searchable fields untuk data terenkripsi
$users->setEncryptionKey($_ENV['DB_ENCRYPTION_KEY']); // Format baru (direkomendasikan) — kontrol per-field $users->setSearchableFields([ 'email' => ['hash' => true], // HMAC-SHA256 blind index (aman) 'username' => ['hash' => false], // Plain text (untuk field non-sensitif) ]); // Format lama (masih didukung) — semua field mendapat perlakuan sama $users->setSearchableFields(['email', 'phone'], true); $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. Key version (v1.2.0) memungkinkan key rotation tanpa re-encrypt manual.
Key Rotation
// Set key lama, lalu rotate ke key baru $users->setEncryptionKey($oldKey, 'v1'); $rotated = $users->rotateEncryptionKey($newKey, 'v2'); // return jumlah dokumen // Set key baru sebagai active $users->setEncryptionKey($newKey, 'v2');
Lihat contoh 21 (
21-key-rotation.php) untuk demo lengkap termasukreencryptAll().
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
enummenggunakan strict comparison. Misalnya, nilai0,false, dan'0'dianggap berbeda.
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.
Lihat docs/schema-metadata-guide.md untuk panduan lengkap tentang properti metadata (
label,ui,relation, dll.) yang tidak divalidasi otomatis.
TTL (Time-To-Live)
Dokumen bisa di-set untuk auto-expire setelah waktu tertentu:
// Aktifkan TTL pada field 'expires_at' dengan default 1 jam $logs->enableTtl('expires_at', 3600); // Tanpa default TTL (set manual per dokumen) $logs->enableTtl('expires_at'); $logs->insert(['message' => 'temp log']); // otomatis dapat expires_at = now() + 3600 // Insert dengan expiry manual (override default) $logs->insert(['message' => 'short', 'expires_at' => time() + 300]); // Bersihkan dokumen yang sudah expired $removed = $logs->cleanExpired(); // Statistik TTL $stats = $logs->ttlStats();
cleanExpired()harus dipanggil manual (misalnya via cron). BangronDB tidak membersihkan otomatis.
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
$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; // reject deletion } });
Event yang tersedia:
beforeInsert/afterInsertbeforeUpdate/afterUpdatebeforeRemove/afterRemove
Hook adalah primitif yang fleksibel. Bisa digunakan untuk ACL enforcement, audit logging, auto-timestamp, data transformation, dan lain-lain — semuanya di application layer, bukan di core library.
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
$users->createIndex('email'); $users->createIndex('address.city'); $users->createIndex('status', 'idx_status'); $db->dropIndex('idx_status');
Health & Monitoring
$health = $db->getHealthMetrics(); $report = $db->getHealthReport(); $perf = $db->getPerformanceMetrics(); $index = $db->getIndexMetrics(); $coll = $db->getCollectionMetrics(); $db->checkIntegrity(); $db->vacuum();
Change Notification
$lastModified = $users->getLastModified(); // ['version' => 42, 'last_updated' => '2026-06-20T10:30:45+07:00'] $users->notifyChange();
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();
Custom Config
Simpan metadata aplikasi per collection — persisten dan auto-load saat reconnect:
// Simpan ACL, settings, atau metadata lain $users->setCustomConfig('acl', [ 'admin' => ['create', 'read', 'update', 'delete'], 'editor' => ['create', 'read', 'update'], 'viewer' => ['read'], ]); $users->setCustomConfig('max_login_attempts', 3); $users->saveConfiguration(); // Baca kapan saja $acl = $users->getCustomConfig('acl'); $all = $users->getAllCustomConfig();
Sensitive keys (
encryption_key,password,secret,token, dll.) ditolak otomatis dan tidak bisa disimpan viasetCustomConfig. Encryption key 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 sepertiUSRtetap didukung saat dibaca ulang.
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
BangronDB menerapkan beberapa guardrail penting:
| Fitur | Tujuan |
|---|---|
Closure-only untuk $where / $func |
Mencegah RCE |
| Validasi field name | Mencegah injection |
| PRAGMA key escaping | Mencegah SQLite injection |
| Regex hardening (ReDoS) | Mengurangi risiko catastrophic backtracking |
| Validasi path | Mengurangi risiko path traversal |
| Sensitive config key blocking | Mencegah credential leakage |
strict_types=1 |
Type safety |
Lihat juga SECURITY_USAGE_GUIDE.md.
API Ringkas
Client
| Method | Keterangan |
|---|---|
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
| Method | Keterangan |
|---|---|
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
| Method | Keterangan |
|---|---|
insert($document) |
Insert satu/banyak dokumen |
insertMany($documents) |
Insert batch dengan hasil detail |
updateMany($criteria, $data, $options = []) |
Update batch dengan hasil detail |
deleteMany($criteria) |
Delete batch dengan hasil detail |
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 |
aggregate($pipeline) |
Aggregation pipeline |
explain($criteria = null) |
Query plan analysis |
stream($criteria = null, $options = []) |
Cursor streaming (Generator) |
drop() |
Hapus collection |
renameCollection($newName) |
Rename collection |
setIdModeAuto() / setIdModeManual() / setIdModePrefix($prefix) |
Atur mode ID |
setEncryptionKey($key, $version = null) |
Atur key enkripsi + versi |
rotateEncryptionKey($newKey, $newVersion = null) |
Rotasi key enkripsi |
reencryptAll() |
Re-encrypt semua dokumen (bump versi) |
setSearchableFields($fields, $hash = false) |
Atur searchable fields |
removeSearchableField($field, $dropColumn = false) |
Hapus searchable field |
rehashSearchableField($field) |
Rehash blind index (migration) |
setSchema($schema) |
Atur schema |
validate($document) |
Validasi dokumen manual |
enableTtl($field, $seconds = null) |
Aktifkan TTL auto-expiration |
disableTtl() |
Nonaktifkan TTL |
cleanExpired() |
Hapus dokumen expired |
expiredCount() |
Hitung dokumen expired |
ttlStats() |
Status TTL collection |
useSoftDeletes($enabled = true) |
Aktifkan soft delete |
setDeletedAtField($field) |
Custom field name (default: deleted_at) |
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 |
setCustomConfig($key, $value) |
Simpan custom config |
getCustomConfig($key, $default = null) |
Baca custom config |
getAllCustomConfig() |
Baca semua custom config |
Cursor
| Method | Keterangan |
|---|---|
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 dokumen |
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
Lihat folder examples/ untuk contoh end-to-end:
| No | File | Topik |
|---|---|---|
| 01 | 01-quick-start-crud.php |
Quick start CRUD |
| 02 | 02-query-operators.php |
Query operators |
| 03 | 03-encryption-searchable.php |
Enkripsi & searchable fields |
| 04 | 04-schema-validation.php |
Schema validation |
| 05 | 05-bulk-operations.php |
Bulk insert/update/delete |
| 06 | 06-aggregation-pipeline.php |
Aggregation pipeline |
| 07 | 07-cursor-streaming.php |
Cursor streaming (Generator) |
| 08 | 08-ttl-expiration.php |
TTL auto-expiration |
| 09 | 09-explain-query.php |
Explain query plan |
| 10 | 10-soft-deletes.php |
Soft delete & restore |
| 11 | 11-hooks.php |
Hooks lifecycle |
| 12 | 12-relationships-populate.php |
Relasi & populate |
| 13 | 13-transactions.php |
Transaksi |
| 14 | 14-indexing-health-monitoring.php |
Indexing & health monitoring |
| 15 | 15-dynamic-configuration.php |
Konfigurasi dinamis |
| 16 | 16-multiple-databases.php |
Multiple databases |
| 17 | 17-id-modes-collection-management.php |
ID modes & collection management |
| 18 | 18-security-features.php |
Fitur keamanan |
| 19 | 19-ecommerce-app.php |
Aplikasi e-commerce lengkap |
| 20 | 20-auth-encrypted.php |
Auth dengan enkripsi |
| 21 | 21-key-rotation.php |
Key rotation |
| 22 | 22-rbac-users-roles-permissions.php |
RBAC (pola aplikasi) |
| 23 | 23-acl-relation-type.php |
ACL dengan relation type |
| 24 | 24-dynamic-acl-per-collection.php |
Dynamic ACL per collection |
Dokumentasi
| Dokumen | Deskripsi |
|---|---|
| Getting Started | Panduan cepat instalasi dan penggunaan dasar |
| Fitur Lanjutan | Hooks, soft delete, TTL, enkripsi, aggregation, dan lainnya |
| Query Operators | Daftar lengkap operator query yang didukung |
| Schema & Metadata Guide | Panduan properti schema, validasi aktif, dan metadata |
| Hook Patterns | 8 pola penggunaan hook dalam aplikasi nyata |
| Framework Integration | Integrasi dengan Laravel, Lumen, Slim, Flight, CodeIgniter 4, Symfony, dan lainnya |
| API Reference | Referensi API lengkap |
| Security | Keamanan, enkripsi, dan best practices |
| Roadmap | Fitur yang sudah dan akan diimplementasikan |
Catatan Kompatibilitas
Jika Anda bermigrasi dari perilaku lama yang mengandalkan create implicit saat selectDB() / selectCollection(), lihat:
Kontribusi
Lihat CONTRIBUTING.md.
Lisensi
BangronDB dilisensikan dengan MIT.
herdianrony/bangrondb 适用场景与选型建议
herdianrony/bangrondb 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 419 次下载、GitHub Stars 达 0, 最近一次更新时间为 2026 年 06 月 21 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「nosql」 「database」 「mongodb」 「json」 「sqlite」 「encryption」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 herdianrony/bangrondb 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 herdianrony/bangrondb 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 herdianrony/bangrondb 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Dibi is Database Abstraction Library for PHP
Generates Symfony2 documents, forms and CRUD
The DreamFactory(tm) CouchDB Service.
Store your language lines in the database, yaml or other sources
The CodeIgniter Redis package
A package for automatically encrypting and decrypting Eloquent attributes in Laravel 5.5+, based on configuration settings.
统计信息
- 总下载量: 419
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 38
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-06-21