Modèles et base de données
La couche de données de TubePress : les classes de modèles, le helper Database PDO, les requêtes préparées, le schéma de base de données et les migrations SQL versionnées expliqués.
TubePress communique avec MySQL/MariaDB via deux couches légères : les modèles (une classe statique par entité) et le helper Database (un petit wrapper autour de PDO). Aucun ORM ni query builder à apprendre — seulement des requêtes préparées et des noms de méthodes prévisibles.
La couche modèle
Chaque entité principale possède un modèle dans src/Models/ exposant des méthodes statiques. Les modèles disponibles sont Video, Category, Tag, Performer, Channel, Comment, Page, User, Setting, Favorite, History, Report, ContactMessage, MenuConfig et 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);Les modèles encapsulent les jointures et filtres propres à leur entité — par exemple Video::find() retourne la vidéo avec ses catégories, tags, interprètes et chaînes attachés, ce qui simplifie les contrôleurs et les templates.
Le helper Database
Pour tout ce qu'un modèle ne couvre pas déjà, utilisez le helper Database directement. Chaque méthode utilise des requêtes préparées — ne concaténez jamais une saisie utilisateur dans une requête SQL.
| Méthode | Retourne | Utilité |
|---|---|---|
Database::fetchOne($sql, $params) | array\|null | Première ligne correspondante. |
Database::fetchAll($sql, $params) | array | Toutes les lignes correspondantes. |
Database::insert($table, $data) | int | Insère un tableau associatif ; retourne le nouvel identifiant. |
Database::update($table, $data, $where, $whereParams) | int | Mise à jour ; retourne les lignes affectées. |
Database::delete($table, $where, $params) | int | Suppression ; retourne les lignes affectées. |
Database::count($table, $where, $params) | int | Nombre de lignes. |
Database::query($sql, $params) | PDOStatement | Toute requête, pour un contrôle total. |
Database::transaction($callback) | mixed | Exécute une closure dans une transaction (commit/rollback automatique). |
$rows = Database::fetchAll(
"SELECT * FROM videos WHERE status = ? ORDER BY id DESC LIMIT ?",
['published', 20]
);
$newId = Database::insert('categories', [
'name' => 'Amateur',
'slug' => 'amateur',
]);utf8mb4, de vraies requêtes préparées (sans émulation) et le mode erreur par exception, et il se reconnecte automatiquement une fois en cas de véritable erreur « server has gone away » — ainsi les workers de longue durée survivent à un timeout MySQL inactif.Transactions
Enveloppez les écritures en plusieurs étapes pour qu'elles réussissent toutes ou soient toutes annulées :
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,
]);
}
});Le schéma
La base de données utilise un schéma MySQL propre et normalisé. Les tables principales comprennent users, settings, categories, tags, performers, channels, videos et les tables de jointure video_categories, video_tags, video_performers — ainsi que comments, user_favorites, user_history, video_likes, pages, plugins, themes et migrations. Les sous-systèmes optionnels ajoutent leurs propres tables (jobs d'import, stockages média, jobs/serveurs de transcodage, zones/spots publicitaires, signalements, sources de flux, tables de traduction, etc.) au fur et à mesure de leur activation.
Migrations
Les modifications du schéma se trouvent dans sql/ sous forme de fichiers numérotés — 001_users.sql, 002_settings.sql, … — appliqués dans l'ordre par Migrator::run() lors de l'installation et après chaque mise à jour. Chaque migration est additive et enregistrée dans la table migrations afin de n'être jamais exécutée deux fois.
- Pour étendre le schéma depuis un plugin, fournissez vos instructions
CREATE TABLEet exécutez-les dans la méthodeinstall()du plugin (voir Hooks & plugins). - Ne renumérotez jamais une migration appliquée et ne la modifiez pas — ajoutez-en une nouvelle avec un numéro supérieur.
Écrire un modèle
Un modèle est simplement une classe statique qui encapsule le helper Database pour une table :
class Promo
{
public static function current(): ?array
{
return Database::fetchOne(
"SELECT * FROM promos WHERE active = 1
ORDER BY id DESC LIMIT 1"
);
}
}Étapes suivantes
Toujours bloqué ?
Ouvrez un ticket depuis votre tableau de bord et notre équipe vous assistera.