Torna al blog

SleekDB: Un Database NoSQL Flat-File per PHP — Quando Usarlo e Quando Evitarlo

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
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.