Saltar al contenido
TubePress — gratuito, autoalojado & con mantenimiento activo
Referencia para desarrolladores

Modelos y base de datos

La capa de datos de TubePress: las clases de modelo, el asistente de base de datos PDO, las consultas preparadas, el esquema de la base de datos y las migraciones SQL versionadas, explicado todo en detalle.

TubePress se comunica con MySQL/MariaDB a través de dos capas ligeras: los modelos (una clase estática por entidad) y el helper Database (un pequeño envoltorio sobre PDO). No hay ORM ni constructor de consultas que aprender — solo sentencias preparadas y nombres de métodos predecibles.

La capa de modelos

Cada entidad principal tiene un modelo en src/Models/ que expone métodos estáticos. Los modelos disponibles son Video, Category, Tag, Performer, Channel, Comment, Page, User, Setting, Favorite, History, Report, ContactMessage, MenuConfig y 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);

Los modelos encapsulan los joins y filtros específicos de su entidad — por ejemplo, Video::find() devuelve el vídeo con sus categorías, etiquetas, intérpretes y canales asociados, de modo que los controladores y las plantillas permanezcan simples.

El helper Database

Para todo lo que un modelo no cubra, usa el helper Database directamente. Cada método utiliza sentencias preparadas — nunca concatenes entradas del usuario en SQL.

MétodoDevuelvePropósito
Database::fetchOne($sql, $params)array\|nullPrimera fila coincidente.
Database::fetchAll($sql, $params)arrayTodas las filas coincidentes.
Database::insert($table, $data)intInserta un array asociativo; devuelve el nuevo id.
Database::update($table, $data, $where, $whereParams)intActualiza; devuelve las filas afectadas.
Database::delete($table, $where, $params)intElimina; devuelve las filas afectadas.
Database::count($table, $where, $params)intConteo de filas.
Database::query($sql, $params)PDOStatementCualquier sentencia, para control total.
Database::transaction($callback)mixedEjecuta un cierre en una transacción (commit/rollback automático).
$rows = Database::fetchAll(
    "SELECT * FROM videos WHERE status = ? ORDER BY id DESC LIMIT ?",
    ['published', 20]
);

$newId = Database::insert('categories', [
    'name' => 'Amateur',
    'slug' => 'amateur',
]);
Conexiones resilientes. El helper utiliza utf8mb4, sentencias preparadas reales (sin emulación) y modo de error por excepción, y se reconecta automáticamente una vez ante un error genuino de "server has gone away" — de modo que los trabajadores de larga duración sobreviven a un tiempo de espera inactivo de MySQL.

Transacciones

Envuelve escrituras de varios pasos para que todas tengan éxito o todas se reviertan:

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

El esquema

La base de datos utiliza un esquema MySQL limpio y normalizado. Las tablas principales incluyen users, settings, categories, tags, performers, channels, videos y las tablas de unión video_categories, video_tags, video_performers — más comments, user_favorites, user_history, video_likes, pages, plugins, themes y migrations. Los subsistemas opcionales añaden sus propias tablas (trabajos de importación, almacenamientos de medios, trabajos/servidores de transcodificación, zonas/spots publicitarios, informes, fuentes de feeds, tablas de traducción y más) a medida que los activas.

Migraciones

Los cambios de esquema se encuentran en sql/ como archivos numerados — 001_users.sql, 002_settings.sql, … — aplicados en orden por Migrator::run() durante la instalación y después de cada actualización. Cada migración es aditiva y se registra en la tabla migrations para que nunca se ejecute dos veces.

  • Para extender el esquema desde un plugin, incluye tus sentencias CREATE TABLE y ejecútalas en el método install() del plugin (ver Hooks & plugins).
  • Nunca renumeres ni edites una migración ya aplicada — añade una nueva con un número mayor.

Escribir un modelo

Un modelo es simplemente una clase estática que envuelve el helper Database para una tabla:

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

Próximos pasos

¿Todavía con dudas?

Abre un ticket desde tu panel y nuestro equipo te ayudará.

Prueba la demo en vivo → Descargar TubePress →