Vai al contenuto
TubePress — gratuito, self-hosted & attivamente mantenuto
Riferimento per sviluppatori

Modelli e database

Il livello dati di TubePress: classi modello, l'helper PDO Database, prepared statement, lo schema del database e le migrazioni SQL versionate spiegate.

TubePress comunica con MySQL/MariaDB attraverso due livelli sottili: i modelli (una classe statica per entità) e il helper Database (un piccolo wrapper su PDO). Non c'è nessun ORM e nessun query builder da imparare — solo prepared statement e nomi di metodo prevedibili.

Il livello dei modelli

Ogni entità principale ha un modello in src/Models/ che espone metodi statici. I modelli disponibili sono Video, Category, Tag, Performer, Channel, Comment, Page, User, Setting, Favorite, History, Report, ContactMessage, MenuConfig e FooterConfig.

$video  = Video::find($id);            // one row (or null)
$latest = Video::all(['status' => 'published', 'limit' => 20]);
$id     = Video::create($data);        // returns new id
Video::update($id, ['title' => 'New title']);
Video::delete($id);

I modelli incapsulano i join e i filtri specifici della loro entità — ad esempio Video::find() restituisce il video con le sue categorie, tag, performer e canali allegati, in modo che i controller e i template rimangano semplici.

Il helper Database

Per tutto ciò che un modello non copre già, utilizza il helper Database direttamente. Ogni metodo usa prepared statement — non concatenare mai l'input dell'utente in SQL.

MetodoRestituisceScopo
Database::fetchOne($sql, $params)array\|nullPrima riga corrispondente.
Database::fetchAll($sql, $params)arrayTutte le righe corrispondenti.
Database::insert($table, $data)intInserisce un array associativo; restituisce il nuovo id.
Database::update($table, $data, $where, $whereParams)intAggiorna; restituisce le righe interessate.
Database::delete($table, $where, $params)intElimina; restituisce le righe interessate.
Database::count($table, $where, $params)intConteggio righe.
Database::query($sql, $params)PDOStatementQualsiasi istruzione, per il controllo completo.
Database::transaction($callback)mixedEsegue una closure in una transazione (commit/rollback automatici).
$rows = Database::fetchAll(
    "SELECT * FROM videos WHERE status = ? ORDER BY id DESC LIMIT ?",
    ['published', 20]
);

$newId = Database::insert('categories', [
    'name' => 'Amateur',
    'slug' => 'amateur',
]);
Connessioni resilienti. Il helper usa utf8mb4, veri prepared statement (senza emulazione) e la modalità di errore a eccezione, e si riconnette automaticamente una volta in caso di un genuino errore "server has gone away" — in modo che i worker a lunga esecuzione sopravvivano a un timeout MySQL inattivo.

Transazioni

Avvolgi le scritture multi-step in modo che abbiano tutte successo o vengano tutte annullate:

Database::transaction(function () use ($videoId, $catIds) {
    Database::delete('video_categories', 'video_id = ?', [$videoId]);
    foreach ($catIds as $cid) {
        Database::insert('video_categories', [
            'video_id' => $videoId, 'category_id' => $cid,
        ]);
    }
});

Lo schema

Il database utilizza uno schema MySQL pulito e normalizzato. Le tabelle principali includono users, settings, categories, tags, performers, channels, videos e le tabelle di join video_categories, video_tags, video_performers — più comments, user_favorites, user_history, video_likes, pages, plugins, themes e migrations. I sottosistemi opzionali aggiungono le proprie tabelle (job di importazione, archivi multimediali, job/server di transcodifica, zone/spot pubblicitari, report, fonti di feed, tabelle di traduzione e altro ancora) man mano che li abiliti.

Migrazioni

Le modifiche allo schema risiedono in sql/ come file numerati — 001_users.sql, 002_settings.sql, … — applicati in ordine da Migrator::run() durante l'installazione e dopo ogni aggiornamento. Ogni migrazione è additiva e registrata nella tabella migrations, quindi non viene mai eseguita due volte.

  • Per estendere lo schema da un plugin, includi le istruzioni CREATE TABLE ed eseguile nel metodo install() del plugin (vedi Hook e plugin).
  • Non rinumerare né modificare una migrazione già applicata — aggiungi una nuova con numero più alto.

Scrivere un modello

Un modello è semplicemente una classe statica che avvolge il helper Database per una singola tabella:

class Promo
{
    public static function current(): ?array
    {
        return Database::fetchOne(
            "SELECT * FROM promos WHERE active = 1
             ORDER BY id DESC LIMIT 1"
        );
    }
}

Passi successivi

Ancora bloccato?

Apri un ticket dalla tua dashboard e il nostro team ti aiuterà.

Prova la demo live → Scarica TubePress →