Ir para o conteúdo
TubePress — gratuito, auto-hospedado & ativamente mantido
Referência para desenvolvedores

Models e banco de dados

A camada de dados do TubePress: classes de model, o helper Database do PDO, prepared statements, o esquema do banco de dados e as migrações SQL versionadas explicadas.

TubePress se comunica com MySQL/MariaDB por meio de duas camadas simples: modelos (uma classe estática por entidade) e o helper Database (um pequeno wrapper sobre PDO). Não há ORM nem query builder para aprender — apenas prepared statements e nomes de métodos previsíveis.

A camada de modelos

Cada entidade principal possui um modelo em src/Models/ que expõe métodos estáticos. Os modelos disponíveis são 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);

Os modelos encapsulam os joins e filtros específicos de cada entidade — por exemplo, Video::find() retorna o vídeo com suas categorias, tags, performers e canais associados, mantendo os controllers e templates simples.

O helper Database

Para qualquer coisa que um modelo não cubra, use o helper Database diretamente. Todos os métodos utilizam prepared statements — nunca concatene entradas do usuário em SQL.

MétodoRetornaFinalidade
Database::fetchOne($sql, $params)array\|nullPrimeira linha correspondente.
Database::fetchAll($sql, $params)arrayTodas as linhas correspondentes.
Database::insert($table, $data)intInsere um array associativo; retorna o novo id.
Database::update($table, $data, $where, $whereParams)intAtualiza; retorna as linhas afetadas.
Database::delete($table, $where, $params)intExclui; retorna as linhas afetadas.
Database::count($table, $where, $params)intContagem de linhas.
Database::query($sql, $params)PDOStatementQualquer instrução, para controle total.
Database::transaction($callback)mixedExecuta uma closure em uma transação (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',
]);
Conexões resilientes. O helper utiliza utf8mb4, prepared statements reais (sem emulação) e modo de erro por exceção, e reconecta automaticamente uma vez em caso de erro genuíno de "server has gone away" — assim, workers de longa duração sobrevivem a um timeout ocioso do MySQL.

Transações

Agrupe escritas em múltiplas etapas para que todas sejam bem-sucedidas ou revertidas:

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

O esquema

O banco de dados utiliza um esquema MySQL limpo e normalizado. As tabelas principais incluem users, settings, categories, tags, performers, channels, videos e as tabelas de junção video_categories, video_tags, video_performers — além de comments, user_favorites, user_history, video_likes, pages, plugins, themes e migrations. Subsistemas opcionais adicionam suas próprias tabelas (jobs de importação, armazenamentos de mídia, jobs/servidores de transcodificação, zonas/spots de anúncios, relatórios, fontes de feed, tabelas de tradução e mais) conforme são habilitados.

Migrações

As alterações de esquema ficam em sql/ como arquivos numerados — 001_users.sql, 002_settings.sql, … — aplicados em ordem por Migrator::run() durante a instalação e após cada atualização. Cada migração é aditiva e registrada na tabela migrations, portanto nunca é executada duas vezes.

  • Para estender o esquema a partir de um plugin, inclua suas instruções CREATE TABLE e execute-as no método install() do plugin (consulte Hooks & plugins).
  • Nunca renumere ou edite uma migração já aplicada — adicione uma nova com número maior.

Criando um modelo

Um modelo é apenas uma classe estática que encapsula o helper Database para uma tabela:

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

Próximos passos

Ainda com dúvidas?

Abra um ticket pelo painel e nossa equipe vai ajudá-lo.

Experimente o demo ao vivo → Baixar TubePress →