Перейти к содержимому
TubePress — бесплатный, самостоятельный & активно поддерживаемый
Справочник разработчика

Модели и база данных

Слой данных TubePress: классы моделей, хелпер Database на основе PDO, подготовленные запросы, схема базы данных и версионируемые SQL-миграции.

TubePress работает с MySQL/MariaDB через два тонких слоя: модели (один статический класс на сущность) и вспомогательный класс Database (небольшая обёртка над PDO). Здесь нет ORM и нет построителя запросов — только подготовленные выражения и предсказуемые имена методов.

Слой моделей

У каждой основной сущности есть модель в src/Models/, предоставляющая статические методы. Доступные модели: Video, Category, Tag, Performer, Channel, Comment, Page, User, Setting, Favorite, History, Report, ContactMessage, MenuConfig и 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);

Модели инкапсулируют объединения и фильтры, специфичные для своей сущности — например, Video::find() возвращает видео вместе с прикреплёнными категориями, тегами, исполнителями и каналами, что упрощает контроллеры и шаблоны.

Вспомогательный класс Database

Для всего, что не охватывают модели, используйте вспомогательный класс Database напрямую. Каждый метод использует подготовленные выражения — никогда не конкатенируйте пользовательский ввод в SQL.

МетодВозвращаетНазначение
Database::fetchOne($sql, $params)array\|nullПервая подходящая строка.
Database::fetchAll($sql, $params)arrayВсе подходящие строки.
Database::insert($table, $data)intВставляет ассоциативный массив; возвращает новый id.
Database::update($table, $data, $where, $whereParams)intОбновляет; возвращает количество затронутых строк.
Database::delete($table, $where, $params)intУдаляет; возвращает количество затронутых строк.
Database::count($table, $where, $params)intКоличество строк.
Database::query($sql, $params)PDOStatementЛюбой запрос, для полного контроля.
Database::transaction($callback)mixedВыполняет замыкание в транзакции (авто 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, настоящие подготовленные выражения (без эмуляции) и режим ошибок через исключения, а также автоматически переподключается один раз при реальной ошибке «server has gone away» — что позволяет долго работающим процессам переживать простой MySQL по таймауту.

Транзакции

Оберните многошаговые операции записи так, чтобы они либо все выполнились, либо все откатились:

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

Схема базы данных

База данных использует чистую нормализованную схему MySQL. Основные таблицы включают users, settings, categories, tags, performers, channels, videos и связующие таблицы video_categories, video_tags, video_performers — а также comments, user_favorites, user_history, video_likes, pages, plugins, themes и migrations. Дополнительные подсистемы добавляют собственные таблицы (задания импорта, хранилища медиа, задания/серверы транскодирования, рекламные зоны/споты, отчёты, источники фидов, таблицы переводов и другое) по мере их включения.

Миграции

Изменения схемы хранятся в sql/ в виде пронумерованных файлов — 001_users.sql, 002_settings.sql, … — применяемых по порядку с помощью Migrator::run() при установке и после каждого обновления. Каждая миграция является аддитивной и записывается в таблицу migrations, поэтому она никогда не выполняется дважды.

  • Чтобы расширить схему из плагина, включите в него операторы CREATE TABLE и выполните их в методе плагина install() (см. Хуки и плагины).
  • Никогда не перенумеруйте и не редактируйте применённую миграцию — добавьте новую с более высоким номером.

Написание модели

Модель — это просто статический класс, оборачивающий вспомогательный класс Database для одной таблицы:

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

Следующие шаги

Остались вопросы?

Откройте заявку в панели управления, и наша команда поможет.

Попробовать демо → Скачать TubePress →