主题开发
打造你自己的主题:目录结构、theme.json、functions.php、模板与辅助函数。
TubePress 主题是一个包含 PHP 模板及可选资源和辅助函数的文件夹。当 外观 和主题编辑器不够用、您希望完全掌控标记时,可使用自定义主题。本页面是构建指南;请将 主题 API 参考 保持在旁边,以查阅变量和辅助函数的完整列表。
贯穿始终的黄金法则:读取 TubePress 注入的设置,而不是硬编码。如果您遵循以 $_ 为前缀的变量,您的主题将完全可从管理后台进行配置,就像内置的 Simply 主题一样。
主题结构
主题存放在 themes/{slug}/ 下。只有 theme.json 和 templates/layout.php 是严格必需的 — 其余所有内容都是可选的,并会回退到 Simply。
themes/aurora/
├── theme.json Required — metadata
├── functions.php Enqueue assets, helper functions
├── assets/
│ ├── css/style.css
│ └── js/app.js
└── templates/
├── layout.php Required — the HTML shell
├── home.php Homepage
├── video.php Watch page
├── category.php …tag/performer/channel (+ plurals)
├── search.php Search results
├── page.php Static page
├── favorites.php User favourites
├── history.php Watch history
├── 404.php Not found
├── auth/ login, register, profile
└── partials/
└── video-card.php Reusable card partialtheme.json
此清单文件是必需的。它包含主题的元数据、可选的默认颜色集以及任意 settings。name、version 和 author 会显示在 /admin/themes 中。
{
"name": "Aurora",
"description": "A custom theme for TubePress",
"version": "1.0.0",
"author": "Your Name",
"screenshot": "screenshot.png",
"colors": {
"primary": "#2563eb",
"secondary": "#7c3aed",
"background": "#ffffff",
"text": "#1e293b"
},
"settings": {
"videos_per_row": 4
}
}functions.php
此文件在启动时自动加载。使用它来注册样式表和脚本,并定义模板调用的辅助函数。使用 filemtime() 查询字符串注册资源,以确保浏览器始终获取最新编辑;第二个参数是加载优先级(数值越小越先加载)。
<?php
declare(strict_types=1);
// filemtime() busts the cache on every edit.
$cssVer = @filemtime(ThemeManager::themePath()
. '/assets/css/style.css') ?: time();
$jsVer = @filemtime(ThemeManager::themePath()
. '/assets/js/app.js') ?: time();
ThemeRenderer::enqueueCSS(
ThemeManager::assetUrl('css/style.css') . '?v=' . $cssVer, 1);
ThemeRenderer::enqueueJS(
ThemeManager::assetUrl('js/app.js') . '?v=' . $jsVer, 1);
// A reusable video-card helper, called from listing templates.
function auroraVideoCard(array $video): string
{
// Record an impression so the CTR system can rank this card.
ImpressionTracker::collect((int) $video['id']);
// Let a plugin replace the card entirely if it wants to.
$card = HookSystem::applyFilter('video.card.html', '', $video);
if ($card !== '') {
return $card;
}
ob_start();
require ThemeManager::templatePath('partials/video-card');
return ob_get_clean();
}Simply 正是定义了这类辅助函数——simplyVideoCard()——以及 simplyPagination() 和 simplySortTabs()。ImpressionTracker::collect() 调用正是为 CTR 排名 提供数据;批量写入会在 layout.php 中稍后刷新。
ThemeManager::templatePath() 和输出缓冲渲染 partials/video-card.php,如上所示。这样可以将标记集中在一处,并允许插件通过 video.card.html 过滤器覆盖它。模板与渲染流程
控制器将数据传递给 ThemeRenderer::render($template, $data),然后渲染器接管后续工作。了解执行顺序有助于您知晓各处可用的内容。
- 控制器渲染。 例如
ThemeRenderer::render('home', ['videos' => $videos])。 - 注入全局变量。 以
$_为前缀的站点、外观、区域设置及卡片/观看变量被添加进来。 - 插件调整数据。
theme.template_data过滤器运行,接收参数($data, $templateName)。 - 您的模板进行缓冲。 模板文件被捕获到
$content中。 - 布局加载。
layout.php接收$content及所有变量,并输出完整的 HTML 框架。 - 印象数据刷新。
ImpressionTracker::flush()在</body>之前写入批量 CTR 更新。 - Cron 运行。
CronManager::run()执行所有到期的计划任务。
您的 layout.php 负责框架:在 <head> 中包含 ThemeRenderer::renderCSS() 和 $_colorOverrides,输出 $content,然后在 </body> 之前调用 ThemeRenderer::renderJS() 和 ImpressionTracker::flush()。主题 API 列出了完整的八项检查清单。
全局变量与辅助函数
每个模板都接收全局 $_ 变量及其自身数据。主题 API 参考 记录了所有内容;以下是最常用的变量。
| 最常用的变量 | 用途 |
|---|---|
$_siteName, $_siteUrl, $_user | 站点标识和已登录用户(或 null)。 |
$_videosPerRow | 列表页的网格列数(4、5 或 6)。 |
$_colorOverrides | <head> 中颜色自定义属性的 <style> 块。 |
$_card*, $_watch* | 在外观中设置的卡片和观看页开关。 |
$_menuItems, $_menuSearch | 导航项目和搜索栏开关。 |
| 关键辅助函数 | 用途 |
|---|---|
ThemeRenderer | ::enqueueCSS/::enqueueJS、::partial、::renderCSS/::renderJS。 |
ThemeManager | ::assetUrl、::themePath、::templatePath、::active。 |
Format | ::number、::duration、::timeAgo,用于格式化显示。 |
Router / url() | URL,以及用于表单的 ::csrfField()。 |
Setting、__() | 读取设置;翻译键值。 |
模板回退
如果当前主题缺少某个模板,TubePress 将改用 Simply 的版本。这意味着您只需覆盖想要更改的部分:从复制单个模板开始——例如 home.php——放入您的主题中,其余内容继续从 Simply 继承,直到您准备好接管为止。一个主题可以只有一个文件,也可以有五十个。
主题钩子
除模板之外,少量钩子点允许您(和插件)在不派生的情况下扩展页面。动作(Action)是即触即忘的;过滤器(Filter)转换您返回的值。
| 钩子 | 类型 | 用途 |
|---|---|---|
head.meta | 动作 | 在 <head> 内输出标签(meta、JSON-LD、验证标签)。 |
footer.scripts | 动作 | 在 </body> 之前输出标记。 |
video.card.html | 过滤器 | 替换卡片的 HTML。参数为 ($html, $video);返回非空字符串以覆盖默认值。 |
// An action — fire and forget, inside <head>.
HookSystem::doAction('head.meta');
// A filter — return '' to keep the default card.
HookSystem::addFilter('video.card.html',
function (string $html, array $video): string {
return $html;
});还有两个过滤器值得了解:theme.template_data 用于在渲染前调整数据数组,head.css 用于追加 <style> 字符串——Simply 使用后者将其网格间距和圆角以 CSS 变量的形式发布。有关更广泛的动作/过滤器目录,请参阅 钩子与插件。