主题开发文档

纸鱼博客主题负责站点前台的布局、样式和交互。主题放在站点根目录的 themes/ 下,每个主题使用一个独立目录。

主题目录

主题目录名只能使用小写字母、数字、下划线和连字符,长度为 1 到 50 个字符。

一个最小主题至少需要 theme.json 和一个模板或资源文件:

themes/example/
├── theme.json
├── header.php
├── footer.php
├── index.php
├── post.php
├── style.css
└── theme.css

theme.json

name 必须与目录名一致,titleversion 为必填项:

{
  "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 中的字段会显示在后台“外观 → 当前主题设置”页面。支持的类型有:texttextareacheckboxswitcherselectradiocolorimage

常用字段:

字段

说明

key

设置键,只应使用稳定、唯一的英文标识

label

后台显示名称

type

控件类型

group

设置分组

default

默认值

options

selectradio 的选项对象

placeholder

输入提示

在模板中读取主题设置:

<?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 只能使用小写字母、数字、下划线和连字符。

模板文件

主题可以覆盖以下系统模板:

文件

用途

header.php

HTML 头部、导航和侧边栏

footer.php

页脚和全局脚本

index.php

首页文章列表

post.php

文章详情

page.php

独立页面

category.php

分类文章列表

tag.php

标签文章列表

search.php

搜索结果

archives.php

文章归档

profile.php

用户资料页

error.php

404 和错误页

plugin-page.php

插件前台页面外壳

模板使用 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$listBaseUrl

  • post.php$post$contentHtml$locked$customFields$related$prevPost$nextPost

  • page.php$page$contentHtml,其中 $page['template'] 是页面模板标识

  • 列表项:文章标题、slug、摘要、封面、发布时间、作者、分类、标签和统计数据

变量的完整形状可以参考 app/Views/theme/ 下的系统默认模板。

公共函数

主题模板可以使用以下常用函数:

函数

用途

get_header() / get_footer()

渲染主题头部和页脚

render_partial($name, $data)

渲染局部模板

url_to($path)

生成站内链接,自动适配伪静态和子目录

asset_url($path)

生成 public/ 下资源地址

theme_asset_url($theme, $path)

生成主题资源地址

theme_value($key, $default)

读取主题设置

settings($key, $default)

读取站点设置

md($markdown)

将 Markdown 渲染为 HTML

e($value)

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_injectsidebar_injectfooter.php 应保留 footer_inject。删除这些调用会导致插件的前台功能失效。

安装和测试

  1. 将主题目录放入 themes/

  2. 确认 theme.json 合法,且 name 与目录名一致。

  3. 在后台“外观”页面检查主题信息并启用。

  4. 访问首页、文章、分类、搜索和独立页面,检查桌面与移动端显示。

  5. 主题完成后可以压缩为 zip,从后台上传安装或提交到应用商店。

主题压缩包上限为 10MB,压缩包应只包含一个顶层主题目录。主题更新失败时系统会恢复原版本。

开发建议

  • 不要直接修改 app/Views/theme/ 中的系统默认模板。

  • 不要把数据库密码、API Key 或其他密钥写入主题。

  • 所有用户输入和设置值都要转义;只有系统生成的 $contentHtml 可以按 HTML 输出。

  • 保持 theme.json 中的设置键稳定,修改键名会使用户之前保存的设置无法自动迁移。

评论区

写下评论

1000 字内

昵称必填,邮箱不会公开。评论提交后会先进入审核。

全部评论

0

还没有评论,欢迎留下你的补充或反馈。