纸鱼博客主题负责站点前台的布局、样式和交互。主题放在站点根目录的 themes/ 下,每个主题使用一个独立目录。
主题目录
主题目录名只能使用小写字母、数字、下划线和连字符,长度为 1 到 50 个字符。
一个最小主题至少需要 theme.json 和一个模板或资源文件:
themes/example/
├── theme.json
├── header.php
├── footer.php
├── index.php
├── post.php
├── style.css
└── theme.csstheme.json
name 必须与目录名一致,title 和 version 为必填项:
{
"name": "example",
"title": "示例主题",
"version": "1.0.0",
"description": "一个 Pafish 主题",
"author": "你的名字",
"authorUrl": "https://example.com",
"homepage": "https://example.com/example-theme",
"settings": [
{
"key": "accent_color",
"label": "主题色",
"type": "color",
"group": "外观",
"default": "#2563eb"
}
]
}主题设置
settings 中的字段会显示在后台“外观 → 当前主题设置”页面。支持的类型有:text、textarea、checkbox、switcher、select、radio、color 和 image。
常用字段:
字段 | 说明 |
|---|---|
| 设置键,只应使用稳定、唯一的英文标识 |
| 后台显示名称 |
| 控件类型 |
| 设置分组 |
| 默认值 |
|
|
| 输入提示 |
在模板中读取主题设置:
<?php $accent = theme_value('accent_color', '#2563eb'); ?>
<a style="color: <?= e($accent) ?>">站点链接</a>文章专属字段
可以通过 editorFields 声明主题使用的文章自定义字段。主题停用后,这些字段数据仍会保留:
{
"editorFields": ["subtitle", "reading_time"]
}页面模板和组件区域
主题可以声明页面编辑器中的模板选项,以及后台组件管理中的自定义区域:
{
"pageTemplates": [
{"name": "landing", "title": "落地页"}
],
"widgetAreas": [
{"key": "sidebar", "label": "侧边栏"},
{"key": "footer", "label": "页脚"}
]
}页面模板标识会写入 $page['template'],主题可以在 page.php 中根据该值选择布局。sidebar 是系统默认区域;自定义区域的 key 只能使用小写字母、数字、下划线和连字符。
模板文件
主题可以覆盖以下系统模板:
文件 | 用途 |
|---|---|
| HTML 头部、导航和侧边栏 |
| 页脚和全局脚本 |
| 首页文章列表 |
| 文章详情 |
| 独立页面 |
| 分类文章列表 |
| 标签文章列表 |
| 搜索结果 |
| 文章归档 |
| 用户资料页 |
| 404 和错误页 |
| 插件前台页面外壳 |
模板使用 PHP 原生语法,不需要额外模板引擎。建议在模板开头标明用途,并使用 e() 转义输出:
<?php
$post = $post ?? [];
get_header();
?>
<article>
<h1><?= e((string) ($post['title'] ?? '')) ?></h1>
<div class="md-content"><?= $contentHtml ?? '' ?></div>
</article>
<?php get_footer(); ?>正文变量 $contentHtml 已经由系统完成 Markdown 渲染,不要再次进行 HTML 转义。标题、链接、属性和用户输入则必须使用 e()。
常用模板变量
header.php:$title、$description、$og,以及站点设置和导航数据index.php:$posts、$pageNum、$totalPages、$listBaseUrlpost.php:$post、$contentHtml、$locked、$customFields、$related、$prevPost、$nextPostpage.php:$page、$contentHtml,其中$page['template']是页面模板标识列表项:文章标题、slug、摘要、封面、发布时间、作者、分类、标签和统计数据
变量的完整形状可以参考 app/Views/theme/ 下的系统默认模板。
公共函数
主题模板可以使用以下常用函数:
函数 | 用途 |
|---|---|
| 渲染主题头部和页脚 |
| 渲染局部模板 |
| 生成站内链接,自动适配伪静态和子目录 |
| 生成 |
| 生成主题资源地址 |
| 读取主题设置 |
| 读取站点设置 |
| 将 Markdown 渲染为 HTML |
| HTML 转义 |
静态资源
style.css:主题布局样式;缺失时回退到默认主题布局样式。theme.css:主题专属样式;系统会以内联<style>的方式加载。其他 CSS、JS、图片和字体可以直接放在主题根目录或
assets/目录。
在模板中使用 theme_asset_url() 获取资源地址,不要拼接服务器绝对路径:
<link rel="stylesheet" href="<?= e(theme_asset_url('example', 'assets/app.css')) ?>">
<script src="<?= e(theme_asset_url('example', 'assets/app.js')) ?>" defer></script>插件挂载点
为了兼容插件,主题应保留系统挂载点:
<?php do_action('head_inject', ['template' => $GLOBALS['pafish_tpl_ctx'] ?? []]); ?>
<?php do_action('sidebar_inject', ['template' => $GLOBALS['pafish_tpl_ctx'] ?? []]); ?>
<?php do_action('footer_inject', ['template' => $GLOBALS['pafish_tpl_ctx'] ?? []]); ?>header.php 应保留 head_inject 和 sidebar_inject,footer.php 应保留 footer_inject。删除这些调用会导致插件的前台功能失效。
安装和测试
将主题目录放入
themes/。确认
theme.json合法,且name与目录名一致。在后台“外观”页面检查主题信息并启用。
访问首页、文章、分类、搜索和独立页面,检查桌面与移动端显示。
主题完成后可以压缩为 zip,从后台上传安装或提交到应用商店。
主题压缩包上限为 10MB,压缩包应只包含一个顶层主题目录。主题更新失败时系统会恢复原版本。
开发建议
不要直接修改
app/Views/theme/中的系统默认模板。不要把数据库密码、API Key 或其他密钥写入主题。
所有用户输入和设置值都要转义;只有系统生成的
$contentHtml可以按 HTML 输出。保持
theme.json中的设置键稳定,修改键名会使用户之前保存的设置无法自动迁移。