Zum Inhalt springen
TubePress — kostenlos, selbst gehostet & aktiv gepflegt
Entwicklerreferenz

Modelle & Datenbank

Die TubePress-Datenschicht erklärt: Modellklassen, der PDO-Database-Helper, Prepared Statements, das Datenbankschema und versionierte SQL-Migrationen.

TubePress kommuniziert mit MySQL/MariaDB über zwei dünne Schichten: Models (eine statische Klasse pro Entität) und den Database-Helfer (ein kleiner Wrapper über PDO). Es gibt kein ORM und keinen Query-Builder zu erlernen — nur Prepared Statements und vorhersehbare Methodennamen.

Die Model-Schicht

Jede Kernentität hat ein Model in src/Models/, das statische Methoden bereitstellt. Die verfügbaren Models sind Video, Category, Tag, Performer, Channel, Comment, Page, User, Setting, Favorite, History, Report, ContactMessage, MenuConfig und 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);

Models kapseln die für ihre Entität spezifischen Joins und Filter — zum Beispiel gibt Video::find() das Video mit seinen Kategorien, Tags, Performern und Channels zurück, sodass Controller und Templates einfach bleiben.

Der Database-Helfer

Für alles, was ein Model nicht bereits abdeckt, verwende den Database-Helfer direkt. Jede Methode verwendet Prepared Statements — niemals Benutzereingaben in SQL verketten.

MethodeRückgabeZweck
Database::fetchOne($sql, $params)array\|nullErste übereinstimmende Zeile.
Database::fetchAll($sql, $params)arrayAlle übereinstimmenden Zeilen.
Database::insert($table, $data)intFügt ein assoziatives Array ein; gibt die neue ID zurück.
Database::update($table, $data, $where, $whereParams)intAktualisiert; gibt betroffene Zeilen zurück.
Database::delete($table, $where, $params)intLöscht; gibt betroffene Zeilen zurück.
Database::count($table, $where, $params)intZeilenanzahl.
Database::query($sql, $params)PDOStatementBeliebige Anweisung, für vollständige Kontrolle.
Database::transaction($callback)mixedFührt einen Closure in einer Transaktion aus (automatischer Commit/Rollback).
$rows = Database::fetchAll(
    "SELECT * FROM videos WHERE status = ? ORDER BY id DESC LIMIT ?",
    ['published', 20]
);

$newId = Database::insert('categories', [
    'name' => 'Amateur',
    'slug' => 'amateur',
]);
Robuste Verbindungen. Der Helfer verwendet utf8mb4, echte Prepared Statements (keine Emulation) und den Ausnahmefehler-Modus, und verbindet sich automatisch einmal neu bei einem echten „Server has gone away"-Fehler — sodass langlebige Worker einen MySQL-Timeout im Leerlauf überstehen.

Transaktionen

Mehrstufige Schreibvorgänge kapseln, sodass sie alle erfolgreich sind oder alle zurückgerollt werden:

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,
        ]);
    }
});

Das Schema

Die Datenbank verwendet ein sauberes, normalisiertes MySQL-Schema. Die Kerntabellen umfassen users, settings, categories, tags, performers, channels, videos und die Join-Tabellen video_categories, video_tags, video_performers — sowie comments, user_favorites, user_history, video_likes, pages, plugins, themes und migrations. Optionale Subsysteme fügen eigene Tabellen hinzu (Import-Jobs, Medienspeicher, Transcode-Jobs/Server, Werbezonen/-spots, Berichte, Feed-Quellen, Übersetzungstabellen und mehr), wenn sie aktiviert werden.

Migrationen

Schemaänderungen liegen in sql/ als nummerierte Dateien vor — 001_users.sql, 002_settings.sql, … — und werden der Reihe nach von Migrator::run() während der Installation und nach jedem Update angewendet. Jede Migration ist additiv und wird in der Tabelle migrations erfasst, sodass sie niemals zweimal ausgeführt wird.

  • Um das Schema aus einem Plugin zu erweitern, liefere deine CREATE TABLE-Anweisungen mit und führe sie in der install()-Methode des Plugins aus (siehe Hooks & Plugins).
  • Niemals eine angewendete Migration umnummerieren oder bearbeiten — füge eine neue mit höherer Nummer hinzu.

Ein Model schreiben

Ein Model ist lediglich eine statische Klasse, die den Database-Helfer für eine Tabelle kapselt:

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

Nächste Schritte

Noch Hilfe benötigt?

Erstellen Sie ein Ticket in Ihrem Dashboard und unser Team hilft Ihnen gerne weiter.

Live-Demo ausprobieren → TubePress herunterladen →