跳转到内容
TubePress — 免费、自托管 & 持续维护
开发者参考

模型与数据库

TubePress 数据层详解:模型类、PDO Database 辅助工具、预处理语句、数据库结构以及版本化 SQL 迁移。

TubePress 通过两个精简层与 MySQL/MariaDB 交互:模型(每个实体一个静态类)和 Database 辅助类(PDO 的轻量封装)。无需学习 ORM 或查询构建器——只需使用预处理语句和规律的方法命名。

模型层

每个核心实体在 src/Models/ 下都有一个暴露静态方法的模型。可用的模型包括 VideoCategoryTagPerformerChannelCommentPageUserSettingFavoriteHistoryReportContactMessageMenuConfigFooterConfig

$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在事务中执行闭包(自动提交/回滚)。
$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 结构。核心表包括 userssettingscategoriestagsperformerschannelsvideos 以及关联表 video_categoriesvideo_tagsvideo_performers,此外还有 commentsuser_favoritesuser_historyvideo_likespagespluginsthemesmigrations。启用可选子系统后,它们会添加各自的表(导入任务、媒体存储、转码任务/服务器、广告区域/位置、举报、Feed 源、翻译表等)。

数据库迁移

数据库结构变更以编号文件的形式存放在 sql/ 目录下——001_users.sql002_settings.sql……在安装时及每次更新后,由 Migrator::run() 按顺序执行。每次迁移均为追加式变更,并记录在 migrations 表中,确保不会重复执行。

  • 如需从插件扩展数据库结构,请将 CREATE TABLE 语句放入插件的 install() 方法中执行(参见 Hooks & plugins)。
  • 切勿对已执行的迁移进行重新编号或修改——请添加编号更大的新迁移。

编写模型

模型本质上是一个静态类,用于封装针对单张表的 Database 辅助调用:

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

下一步

还有疑问?

从您的控制面板提交工单,我们的团队将为您提供帮助。

体验在线演示 → 下载 TubePress →