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.
| Methode | Rückgabe | Zweck |
|---|---|---|
Database::fetchOne($sql, $params) | array\|null | Erste übereinstimmende Zeile. |
Database::fetchAll($sql, $params) | array | Alle übereinstimmenden Zeilen. |
Database::insert($table, $data) | int | Fügt ein assoziatives Array ein; gibt die neue ID zurück. |
Database::update($table, $data, $where, $whereParams) | int | Aktualisiert; gibt betroffene Zeilen zurück. |
Database::delete($table, $where, $params) | int | Löscht; gibt betroffene Zeilen zurück. |
Database::count($table, $where, $params) | int | Zeilenanzahl. |
Database::query($sql, $params) | PDOStatement | Beliebige Anweisung, für vollständige Kontrolle. |
Database::transaction($callback) | mixed | Fü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',
]);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 derinstall()-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.