Модели и база данных
Слой данных 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"
);
}
}Следующие шаги
Остались вопросы?
Откройте заявку в панели управления, и наша команда поможет.