Typecho 与 Single-master 主题:代码逻辑详解

读者定位:产品经理 / 非技术背景同学,了解基本网页概念即可阅读。
本文用"产品语言"拆解 Typecho 博客系统和你正在使用的 Single-master 主题的工作原理。


目录

  1. 前置概念:一个网页是怎么诞生的
  2. Typecho 核心概念(产品语言版)
  3. 一次访问的完整生命周期
  4. Single-master 主题全貌
  5. 模板渲染:页面是怎么"拼"出来的
  6. 数据流:数据库的信息怎么跑到页面上
  7. 前端交互:页面上那些"魔法"怎么实现的
  8. 关键文件逐个讲解(产品经理版)
  9. 相册/照片墙:主题与 Album 插件的协作
  10. 改东西该去哪改?速查表
  11. 常见术语对照表


1. 前置概念:一个网页是怎么诞生的

在深入代码之前,先建立最简单的心智模型:

         "我要看那篇文章"
              ↓
    ① 浏览器发请求(URL)
              ↓
    ② 服务器接收请求
              ↓
    ③ 服务器执行代码
         ┌─ 从数据库取数据
         └─ 把数据填进 HTML 模板
              ↓
    ④ 服务器返回 HTML
              ↓
    ⑤ 浏览器渲染成你看到的页面

Typecho 就是"②③④"这一层。它用 PHP 这种编程语言来"从数据库取数据,拼成网页"。你网站的主题(Single-master)负责的是步骤 ③ 中最外层的工作——把 Typecho 已经取好的数据,填进一个好看的 HTML 模板里。

类比:Typecho = 餐厅的后厨(采购、切菜、备料),主题 = 摆盘和装饰(怎么把做好的菜漂漂亮亮地端到客人面前)。


2. Typecho 核心概念(产品语言版)

Typecho 是一个用 PHP 写的轻量博客系统。理解以下几个概念就够了:

概念 一句话解释 产品类比
Router(路由) 把 URL 翻译成"用户想看什么" 像客服,根据用户说的关键词分派到正确的处理部门
Widget(数据层) 从数据库里取数据的工具 像数据库的查询接口,一句话就能取到文章列表
Theme(主题) 负责"画页面"的那套代码 像 PPT 模板,同一套数据换不同模板就完全不同
Plugin(插件) 给 Typecho 加功能的扩展 像 Chrome 扩展,不改核心代码就能加功能
模板(Template) Theme 里的具体文件,一个文件对应一种页面 像每个页面类型的设计稿

💡 你需要关心的只有两件事:Theme(主题)是你日常改的地方;Plugin(插件)是你装完就很少动的东西。Router 和 Widget 是 Typecho 核心,基本不需要碰。

你的系统架构一览

Typecho 系统分层架构

最外层(绿色块)就是你的主题,里面的核心和数据库一般不用动。


3. 一次访问的完整生命周期

以你博客上的一篇文章为例,URL 是 http://zi-yan.top/index.php/archives/72/

一次访问的完整生命周期

用大白话翻译上面的流程图:

步骤 谁干的? 做了什么?
浏览器 你输入了网址,浏览器发给服务器
Typecho 核心 index.php 是唯一入口,所有请求都经过它,它把系统环境初始化好
Typecho Router 看 URL 里的 archives/72,知道"这是要看第 72 篇文章"
Typecho Widget 连 MySQL 数据库,查 contents 表,取出第 72 篇文章的标题、正文、时间等
插件 如果装了 COS 上传、Album 相册等插件,它们会在此时介入
你的主题 Typecho 把取好的数据“喂给”主题,主题的 post.php 把数据填进 HTML 模板
浏览器 收到完整的 HTML,渲染成你看到的文章页面

💡 关键领悟:主题只参与步骤 ⑥。前面 5 步 Typecho 都帮你做完了。主题的工作就是——Typecho 把菜备好了(数据),你来摆盘(展示)。


4. Single-master 主题全貌

4.1 你的主题有哪些文件?

主题文件结构

按"必知程度"分三个层级:

层级 文件 干什么的
★ 必知 index.php 首页:文章列表
★ 必知 post.php 文章详情页:一篇文章的完整显示
★ 必知 page.php 独立页面:「关于我」等
★ 必知 archive.php 分类/标签/搜索结果页
★ 必知 single.php 工具类(夜间模式、时间格式化等)
★ 必知 functions.php 后台外观设置(12 个开关和输入框)
★ 必知 single.css 所有样式(颜色、布局、字体大小)
★ 必知 single.js 所有交互(夜间模式切换、返回顶部等)
了解即可 header.php HTML 头部 + 页面标题 + 社交分享标签
了解即可 header-nav.php 导航栏:菜单、搜索、登录
了解即可 footer.php 页脚:版权、JS 加载、灯箱初始化
了解即可 comments.php 评论列表 + 发表表单
了解即可 tags.php 标签云模板
了解即可 Multiverse.php 网格图片墙模板
了解即可 custom.php 空白模板,供二次开发用
了解即可 MkEncrypt.php 页面密码保护工具
了解即可 404.php 页面没找到的错误页

⚠️ static/kico.cssstatic/kico.jsstatic/prism.jsstatic/font-awesome/static/Lens/static/Multiverse/ — 这些是第三方库,不要修改

4.2 模板是怎么被自动选用的?

主题模板组织图

重要规律:Typecho 根据"页面类型"自动选用模板。

你访问的 URL Typecho 判断的类型 自动选用 显示效果
/ 首页 index.php 文章列表
/index.php/archives/72/ 单篇文章 post.php 文章详情
/index.php/About.html 独立页面 page.php 「关于我」
/index.php/category/album/ 分类归档 archive.php 该分类下的文章列表
(独立页面 + 后台选了模板) 特殊模板 Multiverse.php / custom.php 网格图片墙、自定义排版等

无论用哪个模板,都遵循同一个骨架:

header.php    →  HTML 头部、标题、导航、CSS
     ↓
index.php 等  →  页面主体内容(文章列表 or 文章 or 自定义内容)
     ↓
footer.php    →  页脚、版权、JavaScript 脚本、灯箱


5. 模板渲染:页面是怎么"拼"出来的

5.1 首页(index.php)是怎么工作的

以你的首页为例,代码逻辑如下(看注释,不需要在意具体语法):

// 第一步:加载公共头部(HTML 框架 + 导航栏)
$this->need('header.php');
?>

<!-- 首页大标题区 -->
<section class="home-title">
<h1><?php $this->options->title() ?></h1>     <!-- ← 显示站点名称,来自后台设置 -->
<span><?php $this->options->description() ?></span>  <!-- ← 显示站点副标题 -->
</section>

<!-- 文章列表 -->
<section class="home-posts">
<?php while($this->next()): ?><!-- ← 循环:一篇文章一次 -->
<div class="post-item">
<h2><a href="<?php $this->permalink() ?>"><?php $this->title() ?></a></h2>
<p><?php $this->excerpt(100); ?></p>     <!-- ← 摘要,截 100 字 -->
<div class="post-meta">
<time><?php $this->date(); ?></time>      <!-- ← 发布日期 -->
<span><?php $this->category(','); ?></span>  <!-- ← 分类 -->
<?php if(显示评论数设置打开了): ?>
<span><?php $this->commentsNum('%d °C'); ?></span>  <!-- ← 评论数 -->
<?php endif; ?>
</div>
</div>
<?php endwhile; ?>
</section>

<?php $this->pageNav('«', '»'); ?><!-- ← 分页:上一页/下一页 -->

<?php $this->need('footer.php'); ?><!-- ← 加载公共页脚 -->

一句话总结:首页 = 一个循环 while($this->next()),把每篇文章的标题、摘要、日期、分类一行一行画出来。分页切换由 pageNav() 自动处理。

5.2 文章页(post.php)的独有功能

与首页不同,文章页多了几个专属区块:

区块 代码位置 功能
老文章提醒 if(time() - $this->modified >= 15552000) 文章修改超过 180 天,显示「这篇文章上次修改于 XXX 天前」
上一篇/下一篇 $this->thePrev() / $this->theNext() 文章底部的导航链接
标签 $this->tags() 显示文章标签(由 functions.phparchive_meta 设置控制)
作者信息 if($this->options->author_text) 如果后台填了"作者信息",显示作者头像+介绍
评论区 $this->need('comments.php') 引入评论模板

5.3 归档页(archive.php)—— 分类/标签/搜索的共用模板

archive.php 复用了首页的列表结构,但多了两件事:

  1. 标题动态变化:在分类页显示「"技术"」,在标签页显示「含标签"生活"的文章」,在搜索页显示「含关键词"typecho"的文章」
  2. 搜索结果为空时:显示「没有找到结果 (QWQ)」

5.4 独立页面(page.php)

和文章页几乎一样,区别是没有上一篇/下一篇、没有标签、没有作者信息。就是一个干净的页面内容显示。


6. 数据流:数据库的信息怎么跑到页面上

这部分是理解"模板里写的东西什么意思"的关键。

数据如何从数据库流到屏幕

核心模式:$this->xxx() = 取数据 + 显示

你在模板里看到的所有 $this->xxxx() 调用,本质上都是 Typecho 已经帮你从数据库取好的数据。记住这个对应表:

模板里的写法 实际取的数据 来自数据库的哪个字段
$this->title() 文章标题 contents.title
$this->content() 文章正文(HTML) contents.text
$this->excerpt(100) 文章摘要(截 100 字) contents.text 的前 100 字
$this->date() 发布日期 contents.created
$this->permalink() 文章链接 动态生成
$this->category() 分类名称 metas
$this->tags() 标签列表 metas
$this->commentsNum() 评论数量 comments 表统计
$this->author() 作者名称 users
$this->options->title() 站点名称 后台设置的"站点名称"
$this->options->description() 站点副标题 后台设置的"站点描述"
$this->options->xxx() 后台各项设置值 functions.php 注册的 12 个设置项
$this->fields->xxx 自定义字段 fields 表(CustomFields 插件)
$this->is('post') 判断当前是否文章页 —(不是数据,是判断条件)

自定义字段:给页面加"额外数据"

Typecho 自带一个"自定义字段"系统。在编辑文章/页面时,可以给页面附加任意键值对。这在相册场景中大量使用:

用法 例子 代码
给页面加描述 about = "这是我的摄影集" $this->fields->about
给页面加密码 password = "123456" $this->fields->password
给页面加社交链接 Twitter = "https://..." $this->fields->Twitter
给照片墙加图片数据 photos = '[{"url":"...","desc":"照片"}]' 通过 CustomFields 插件的 API 读取


7. 前端交互:页面上那些"魔法"怎么实现的

所有你眼睛能看到的交互效果,由两个文件控制:

文件 角色 内容
static/single.css 样式 颜色、布局、字体大小、响应式(手机适配)、夜间模式配色
static/single.js 行为 点击响应、切换状态、动态生成目录等

single.js:Paul_Single 类

前端交互引擎

这个类在页面底部(footer.php)被初始化:

varsingle=newPaul_Single({
copyright:true,// 复制提醒(来自后台 copy_notice 设置)
night:true// 夜间模式(来自后台 night_mode 设置)
});

6 个核心功能:

方法 功能 用户能看到的效果
night() 夜间模式切换 点击左上角图标,全站变暗/变亮
tree() 文章目录生成 文章右侧自动出现"悬浮目录"
to_top() 返回顶部 滚动后右下角出现"↑"按钮
header() 移动端菜单 小屏幕上汉堡菜单展开/收起
comment_list() 评论高亮 @回复时高亮定位到被回复的评论
links() 复制提醒 复制文章内容时弹窗提示

single.css:主题的"皮肤"

single.css 约 500 行,按区域分为 6 块:

区块 行号范围(约) 控制什么
0 全局 变量 + 基础 主题色 --blue: #6f9fc7、字体、夜间模式变量覆写
1 页眉 header 导航栏、汉堡菜单、搜索框样式
2 正文 main 文章排版、目录样式、图片、表格
3 页尾 footer 页脚信息栏、版权区
4 附加 额外 打印样式、Prism 代码块配色

💡 想改颜色?去 single.css:root 里的 CSS 变量,改一个变量全站生效。


8. 关键文件逐个讲解(产品经理版)

8.1 single.php — 核心工具类

这是主题的"瑞士军刀",提供了 4 个全局函数:

方法名 作用 怎么用的
Single::update() 检查主题更新 functions.php 调用,在后台显示更新信息
Single::is_night() 判断夜间模式 header.php<body> 标签里调用,决定加载深色/浅色样式
Single::tran_time($ts) 时间戳转友好格式 comments.php 里用,「3 天前」「2 个月前」就是它算的
Single::post_image() 取文章第一张图 header.php 里用,给社交分享(微信/微博)提供封面图

8.2 functions.php — 后台外观设置

这个文件只有一个函数 themeConfig(),作用是注册 Typecho 后台"外观设置"里的 12 个配置项

你进入 控制台 → 外观 → 设置外观 看到的所有开关和输入框,都来自这个文件:

设置项 类型 作用
favicon 文本框 站点图标
background 文本框 背景图
home_social 文本框 首页社交链接
custom_css 文本框 自定义 CSS
custom_script 文本框 统计代码
author_text 文本框 文章底部作者介绍
night_mode 单选 夜间模式:关闭/自动/始终
copy_notice 单选 复制内容时是否弹窗提醒
widget_set 单选 页脚信息栏:开/关
archive_meta 多选 首页/归档显示哪些元信息
post_meta 多选 文章页显示哪些元信息
hidden_categories 文本框 对未登录用户隐藏的分类

💡 想加一个新设置?在这个文件里参照现有的格式加一行就行。

8.3 header.php — HTML 头部

产出物:网页的 <head> 区域 + <body> 开始标签 + 导航栏引入。

关键内容:
- 页面标题:根据页面类型动态生成(首页显示站名,文章页显示「文章名 - 站名」)
- CSS 加载:kico.css → single.css → Font Awesome 图标
- Open Graph 标签:给微信/微博等社交平台分享用的标题、描述、封面图
- 夜间模式判断Single::is_night() 决定 <body> 有没有 dark-theme 类名

8.4 header-nav.php — 导航栏

产出物:页面顶部的导航条(桌面端 + 移动端)。

包含:
- 夜间模式切换按钮
- 桌面端:登录/用户下拉菜单 + 搜索框
- 移动端:汉堡菜单 → 侧边滑出菜单(首页 / 分类 / 相册 / 关于我 / 进入后台)
- 隐藏分类逻辑:如果在 functions.php 里设了"隐藏分类",未登录用户看不到这些分类
- 遮罩层(点击遮罩关闭菜单)

8.5 footer.php — 页脚 + 所有 JS

产出物:页面底部信息 + 所有 JavaScript 脚本加载。

关键内容:
- 返回顶部按钮 + 目录切换按钮
- 页脚信息栏(可由后台"widget_set"开关控制):最新文章 / 时光机(按月份归档)/ 最近评论
- 版权信息:年份 + 站点名 + 主题 credit + ICP 备案号
- JS 加载顺序:kico.js → single.js → prism.js → 初始化 Paul_Single
- fancybox 灯箱:CDN 加载,图片点击放大

8.6 comments.php — 评论区

产出物:评论列表 + 评论发表表单。

包含:
- 评论者头像:QQ 邮箱用腾讯头像 API,其他邮箱用 Gravatar
- 友好时间:评论时间用 Single::tran_time() 显示(如"3 天前")
- @回复显示:回复时显示「@原作者名」
- 待审核标记:未审核评论显示审核提示
- 响应式表单:已登录用户看简化表单,未登录需要填昵称+邮箱+网址

8.7 MkEncrypt.php — 页面密码加密

一个独立的加密工具,可为 Typecho 独立页面添加密码保护功能。

工作流程
1. 访客打开加密页面 → 显示密码输入框(整页遮罩)
2. 输入正确密码 → 设置 Cookie(存 41 天),显示内容
3. 密码错误 → 显示「密码不对!请重试」
4. 已有 Cookie 的用户 → 直接看内容

💡 任何自定义模板都可以引入 require_once('MkEncrypt.php') 然后通过 $this->fields->password 自定义字段控制是否加密。


9. 相册:Album 插件

你的网站目前通过 Album 插件来展示相册,它有自己的路由(/album/),不经过主题的 index.php / page.php 流程

组件 说明
Album 插件 独立路由 /album/,自带数据库表、上传接口、展示页面
导航链接 header-nav.php 中的「相册」链接指向 /album/
与主题的关系 Album 插件的输出独立于主题,但共享同一套数据库和用户系统

已移除的相册模板

photo-wall.php(瀑布流照片墙)和 Lens.php(全屏相册)已于 2026-07-09 删除。如果你需要新的照片展示方式,使用 Album 插件或创建新的自定义模板。


10. 改东西该去哪改?速查表

你想改什么 去改哪个文件 具体改哪里
站点名称、副标题 Typecho 后台(不是代码!) 控制台 → 设置 → 基本
站点图标、背景图 Typecho 后台 控制台 → 外观 → 设置外观
主题主色调 static/single.css 搜索 --blue: #6f9fc7,改颜色值
夜间模式颜色 static/single.css 搜索 .dark-theme,改里面的颜色变量
导航栏菜单项 header-nav.php 搜索 "首页",改 <a href=...> 标签
首页显示几篇文章 Typecho 后台 控制台 → 设置 → 阅读 → 每页文章数
首页文章列表显示哪些信息 Typecho 后台 控制台 → 外观 → 设置外观 → archive_meta
文章底部作者介绍 Typecho 后台 控制台 → 外观 → 设置外观 → author_text
版权信息文字 footer.php 搜索 "All Rights Reserved"
ICP 备案号 footer.php 搜索 "ICP备案号"
统计代码 Typecho 后台 控制台 → 外观 → 设置外观 → custom_script
加一个新的后台设置项 functions.php 参照现有代码,加一个新的 Form_Element_*
加一种新的页面模板 新建 xxx.php 参照 custom.php,第 2 行加 @package custom
隐藏某些分类 Typecho 后台 控制台 → 外观 → 设置外观 → hidden_categories
评论表单文字 comments.php 搜索 "快来评论支持吧"
404 页文字 404.php 搜索 "页面不见了"
部署到生产 按 MEMORY.md 流程 git checkout main && git merge dev → 打包 → scp


11. 常见术语对照表

技术术语 白话解释
PHP 一种服务器端编程语言,Typecho 用它写的
PHP 模板 后缀 .php 但主要是 HTML 的文件,里面夹了一些 <?php ?> 取数据的代码
$this 指当前页面的"数据对象",你可以把它想象成一篇文章的所有信息
$this->options 网站全局设置(站点名、描述、后台各项开关)
$this->fields 当前页面的"自定义字段"(额外的键值对数据)
$this->need('xxx.php') 加载另一个 PHP 文件进来,类似"在这里插入 header 文件"
Widget Typecho 的数据获取工具,每种数据有一个 Widget(文章、分类、评论各不同)
MySQL 关系型数据库,所有内容(文章、评论、设置)都存在里面
CSS 样式表,控制颜色、字体、布局、响应式
JS(JavaScript) 前端脚本,控制点击响应、动画、切换等交互行为
OG 标签 Open Graph 标签,给微信/微博分享时提供标题和封面图
CDN 内容分发网络,JS/CSS/图片从离用户最近的服务器加载,更快
Cookie 浏览器端的小存储,用来记住"夜间模式"偏好、"加密页面密码"等
路由(Route) URL 和页面模板的对应关系,如 /archives/72post.php
自定义字段(Field) 文章的附加属性,如相册的 "password"、"photos"、"about" 等
fancybox 一个图片灯箱 JS 库,点图片后弹出大图/相册预览


后记

这份文档覆盖了 Typecho 和 Single-master 主题的所有核心逻辑。作为产品经理,你不需要能写代码,但知道每一块代码"管什么"、"在哪里改",会让你和开发协作时事半功倍。

如果某个部分有疑问,或者想深入了解某个特定功能,随时可以问我。


文档生成于 2026-07-09 · 基于 Single-master v2.1 · Typecho 1.2.1