Quando si sviluppa un'applicazione PHP, la scelta del database è una delle prime decisioni architetturali. MySQL, PostgreSQL, SQLite sono le opzioni classiche. Ma cosa succede quando il progetto è piccolo, non vuoi configurare un server di database e hai bisogno di qualcosa di immediato? È qui che entra in gioco SleekDB.
Cos'è SleekDB?
SleekDB è un database NoSQL flat-file scritto interamente in PHP, senza dipendenze esterne. I dati vengono archiviati come semplici file JSON sul filesystem, rendendolo estremamente facile da installare, utilizzare e trasportare. Funziona in modo concettualmente simile a MongoDB, ma con una complessità drasticamente ridotta.
Installazione
L'installazione avviene tramite Composer con un singolo comando:
composer require rakibtg/sleekdb
I requisiti sono minimi: PHP 8.4+ (o PHP 7.x con la versione 2.15), l'estensione ext-json e ext-mbstring. Niente server, niente configurazioni, niente processi in background.
Come Funziona
SleekDB si basa su due concetti fondamentali: Store e Document.
Uno Store è l'equivalente di una tabella SQL o di una collection MongoDB. È semplicemente una directory sul filesystem. Un Document è un singolo record, salvato come file JSON, a cui viene automaticamente assegnato un _id univoco.
$databaseDir = __DIR__ . "/database";
$userStore = new \SleekDB\Store("users", $databaseDir);
Con queste due righe hai creato un database completo. Nessuna migrazione, nessuno schema da definire.
Operazioni CRUD
Inserimento
// Singolo documento
$user = $userStore->insert([
"name" => "Mario Rossi",
"email" => "mario@example.com",
"role" => "admin"
]);
// Inserimento multiplo
$userStore->insertMany([
["name" => "Luigi Bianchi", "role" => "editor"],
["name" => "Anna Verdi", "role" => "viewer"]
]);
Lettura
// Tutti i documenti
$allUsers = $userStore->findAll();
// Per ID (molto veloce, accesso diretto al file)
$user = $userStore->findById(1);
// Con criteri
$admins = $userStore->findBy(["role", "=", "admin"]);
// Un solo risultato
$mario = $userStore->findOneBy(["name", "=", "Mario Rossi"]);
Aggiornamento
// Aggiorna campi specifici per ID
$userStore->updateById(1, ["role" => "superadmin"]);
// Upsert: aggiorna se esiste, crea se non esiste
$userStore->updateOrInsert([
"_id" => 1,
"name" => "Mario Rossi",
"role" => "superadmin"
]);
Cancellazione
// Per ID
$userStore->deleteById(3);
// Per criteri
$userStore->deleteBy(["role", "=", "viewer"]);
Query Avanzate
Dove SleekDB sorprende è nel suo QueryBuilder, che permette di costruire query complesse con un'API fluida:
$results = $userStore->createQueryBuilder()
->where(["status", "=", "active"])
->where(["age", ">=", 18])
->orderBy(["name" => "asc"])
->limit(10)
->skip(20)
->select(["name", "email"])
->getQuery()
->fetch();
Gli operatori supportati sono numerosi: =, !=, >, >=, <, <=, LIKE, NOT LIKE, IN, NOT IN, BETWEEN, EXISTS, CONTAINS. Si possono combinare condizioni con AND e OR:
$results = $userStore->findBy([
[["role", "=", "admin"], "OR", ["role", "=", "editor"]],
"AND",
["status", "=", "active"]
]);
Sono supportati anche join tra store diversi, groupBy, having e ricerca full-text:
// Join
$users = $userStore->createQueryBuilder()
->join(function($user) use ($orderStore) {
return $orderStore->findBy(["userId", "=", $user["_id"]]);
}, "orders")
->getQuery()
->fetch();
// Ricerca full-text
$results = $userStore->createQueryBuilder()
->search(["name", "bio"], "developer PHP")
->getQuery()
->fetch();
Cache Integrata
SleekDB include un sistema di caching automatico che memorizza i risultati delle query. Questo significa che query ripetute vengono servite istantaneamente senza rileggere i file JSON. La cache è configurabile:
$store = new \SleekDB\Store("users", $dataDir, [
"auto_cache" => true,
"cache_lifetime" => 300 // 5 minuti
]);
Pro: Quando SleekDB Brilla
- Zero configurazione: nessun server database da installare o mantenere. Composer require e via.
- Portabilità totale: il database sono file JSON. Copia la cartella e hai il backup. Sposta il progetto e funziona ovunque.
- Schema-free: nessuna migrazione, nessun ALTER TABLE. Ogni documento può avere struttura diversa.
- Nessuna dipendenza: funziona su qualsiasi hosting PHP, anche quelli più economici senza accesso a MySQL.
- API elegante: il QueryBuilder è intuitivo e potente, con supporto a query annidate, join e full-text search.
- Caching integrato: le query ripetute sono servite dalla cache senza overhead.
- Ideale per prototipi e MVP: metti in piedi un'applicazione funzionante in minuti.
- Perfetto per piccoli progetti: blog personali, portfolio, configurazioni, log, dashboard interne.
Contro: Quando Evitarlo
- Non scala: con decine di migliaia di documenti le performance degradano. I file JSON devono essere letti e parsati completamente.
- Nessuna concorrenza robusta: accessi simultanei in scrittura possono causare conflitti. Non c'è un lock manager come nei database tradizionali.
- Nessuna transazione ACID: non puoi fare rollback atomici. Se un'operazione fallisce a metà, i dati possono restare inconsistenti.
- Nessun indice reale: le ricerche sono sequenziali (full scan). Su dataset grandi, ogni query legge tutti i file.
- Nessuna relazione nativa: i join sono simulati via PHP, non ottimizzati a livello di engine.
- Sicurezza: i dati sono file leggibili sul filesystem. Serve protezione a livello di server (permessi, .htaccess).
- Non adatto a produzione ad alto traffico: qualsiasi applicazione con utenti concorrenti significativi richiede un database tradizionale.
- Maturità: community più piccola rispetto a SQLite, meno testato in scenari edge-case.
Confronto Rapido: SleekDB vs SQLite vs MySQL
| Caratteristica | SleekDB | SQLite | MySQL/PostgreSQL |
|---|---|---|---|
| Installazione | Composer | Estensione PHP | Server dedicato |
| Schema | Schema-free | Schema fisso | Schema fisso |
| Formato dati | File JSON | File binario | Server |
| Concorrenza | Limitata | Buona (WAL) | Eccellente |
| Performance (grande) | Scarsa | Buona | Eccellente |
| Performance (piccolo) | Ottima | Ottima | Sovradimensionato |
| Transazioni | No | Sì | Sì |
| Portabilità | Eccellente | Ottima | Scarsa |
| Query complesse | Buone | Ottime (SQL) | Ottime (SQL) |
| Ideale per | Prototipi, MVP | App medio-piccole | Produzione |
Conclusioni
SleekDB occupa una nicchia precisa: è la soluzione ideale quando hai bisogno di persistenza dati in PHP senza la complessità di un database tradizionale. Per prototipi, MVP, piccoli tool interni, configurazioni applicative o progetti personali, è una scelta eccellente che ti permette di essere operativo in pochi secondi.
Tuttavia, nel momento in cui il progetto cresce — più utenti, più dati, più operazioni concorrenti — è il momento di migrare verso SQLite o un database relazionale completo. SleekDB non pretende di sostituirli, e questa onestà progettuale è uno dei suoi punti di forza.
La regola è semplice: se il tuo progetto potrebbe funzionare con un file JSON scritto a mano ma vorresti un'API pulita per interrogarlo, SleekDB è la risposta giusta.