RyeBlog 主题 = 一个目录 + 若干模板文件,不用懂框架,纯 PHP + HTML + CSS。本文以官方「Doc 文档主题」(vuecho)为例,带你从零设计一个主题。
一、主题目录结构
usr/theme/<主题名>/
├── theme.css # 必选:样式 + 元信息(@Title 就是后台显示的名字)
├── home.php # 首页模板(可选,有则接管首页)
├── post.php # 文章页模板(可选)
├── page.php # 独立页模板(可选)
├── category.php # 分类页模板(可选)
├── tag.php # 标签页模板(可选)
├── search.php # 搜索页模板(可选)
├── list_common.php # 列表页公共骨架(分类/标签/搜索共用)
└── theme.js # 主题脚本(可选,自动 defer 加载)主题名:小写字母数字连字符。没有模板文件的页面自动用系统默认渲染,所以只需提供想自定义的页面模板。
二、theme.css 元信息(决定后台显示名)
/* ===========================================================
RyeBlog 文档主题 —— Doc 文档主题
@Title Doc 文档主题
@Desc 左侧文档树 + 三栏阅读 + 夜间模式,设计参考 Typecho Vuecho
@Version 2.0.0
=========================================================== */@Title:后台「外观」页的主题名@Desc:主题描述@Version:云端更新比较版本- 样式建议挂在
body.theme-<名字>作用域下,避免污染后台
三、模板文件怎么写(以 post.php 为例)
文章页模板能直接用这些变量:$post(文章)、$rendered['html'](渲染后正文)、$rendered['toc'](目录数组)、$tags、$prevPost/$nextPost、$comments、$tocList。
<?php
$content = $rendered['html'] ?? L($post, 'content'); // 渲染结果优先
$siteTitle = siteTitle();
$themeCss = baseUrl('usr/theme/doc/theme.css?v=' . filemtime(__DIR__ . '/theme.css'));
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?php echo esc(L($post, 'title')); ?> · <?php echo esc($siteTitle); ?></title>
<link rel="stylesheet" href="<?php echo $themeCss; ?>">
</head>
<body class="theme-doc">
<header>…顶部导航…</header>
<main>
<h1><?php echo esc(L($post, 'title')); ?></h1>
<div class="content"><?php echo $content; ?></div>
</main>
</body>
</html>关键点:
- 正文用
$rendered['html'](已做 Markdown 渲染和标题锚点注入);回退L($post, 'content') - 所有用户内容输出前
esc()转义,防 XSS - 语言感知用
L($post, 'title'),界面文案用__('搜索')
四、首页模板(home.php)
首页模板能拿到 $posts(当前页文章列表)、$result(分页信息)。参考 Doc 文档主题首页:
<?php $posts = getPosts(['perPage' => 10])['items']; // 也可自取 ?>
<section class="hero">
<h1><?php echo esc(getOption('hero_title', siteTitle())); ?></h1>
<p><?php echo esc(getOption('hero_subtitle', siteSlogan())); ?></p>
<a class="btn" href="<?php echo esc(getOption('hero_btn1_url', homeUrl())); ?>">
<?php echo esc(getOption('hero_btn1_text', '快速上手')); ?></a>
</section>用 getOption() 读主题选项——把标题、按钮、特性卡等做成可配置项,后台「外观 → 编辑」页就能改,不用动代码。
五、列表页三件套
分类/标签/搜索页结构几乎一样,做一个 list_common.php 公共骨架,三个薄模板共用:
<?php /* category.php —— 只设变量后 require 公共骨架 */
$listTitle = __('分类:') . L($cat, 'name');
$listTotal = (int)($result['total'] ?? 0);
$listItems = $posts;
$listPages = (int)($result['pages'] ?? 1);
$listPage = (int)($result['page'] ?? 1);
$listPageUrl = function ($i) use ($cat) { return categoryPageUrl($cat, $i); };
require __DIR__ . '/list_common.php';六、主题选项与后台「编辑」
后台「外观 → ✏️ 编辑」提供两个页签:
- 外观配置:
getOption()读取的字段可直接在后台表单修改(如 hero 标题、双按钮、特性卡) - 文件编辑:在线改 home.php / post.php / theme.css 等,PHP 文件保存前自动语法校验
七、打包发布到云端
php tools/cli_pack.php theme <主题名> --version 1.0.0生成 cloud-release/themes/<主题名>-<版本>.zip + 更新 repo.json。上传到云端仓库后,全站用户后台「外观 → 云端主题」即可一键安装、更新。记得 theme.css 里写 @Version,否则按 1.0.0 处理。
八、快速上手清单
mkdir usr/theme/mydoc && touch theme.css home.php post.php- theme.css 写
@Title 我的文档主题+ 基础样式 - home.php 抄 Doc 文档主题的 hero 区,改成自己的
- 后台「外观」→ 激活「我的文档主题」
- 满意后
cli_pack.php theme mydoc --version 1.0.0发云端
RyeBlogRye