テーマ開発
独自テーマの作り方を解説します。構成、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() クエリ文字列でアセットをエンキューすると、ブラウザは常に最新の編集内容を取得できます。第2引数は読み込み優先度(小さいほど早く読み込まれる)です。
<?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 をレンダリングします。マークアップを1箇所にまとめ、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 に8項目のチェックリスト全体が記載されています。
グローバル変数とヘルパー
すべてのテンプレートはグローバルな $_ 変数と固有のデータを受け取ります。テーマ 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 に継承させます。テーマは1ファイルでも50ファイルでも構いません。
テーマフック
テンプレート以外にも、少数のフックポイントを使ってページをフォークせずに拡張できます(プラグインも同様)。アクションはファイアアンドフォーゲット、フィルターは返す値を変換します。
| フック | 種別 | 目的 |
|---|---|---|
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;
});さらに2つのフィルターも重要です。theme.template_data はレンダリング前にデータ配列を調整し、head.css は <style> 文字列を追加します — Simply は後者を使用してグリッドギャップとラジウスを CSS 変数として公開しています。アクション/フィルターのより広いカタログについては、フックとプラグインを参照してください。