YeCha 1.0.0 · 从安装到二次开发的一份完整手册。当前版本 1.0.0,本站现装 34 套主题、20 个插件(均可在 /theme 与 /plugin 在线浏览)。命令均可在生产直接执行;任何改动前先备份(库 + 文件 + 配置)。
本页导航
安装
环境要求
| 项目 | 要求 |
|---|---|
| PHP | 8.1+(推荐 8.3),扩展:pdo_mysql、mbstring、curl、simplexml、fileinfo、zip、openssl |
| 数据库 | MySQL 5.7+ / MariaDB 10.3+,字符集 utf8mb4 |
| Web 服务器 | Nginx 1.20+ 或 Apache 2.4+,需要能配置伪静态 |
| 目录 | 站点根目录可写(uploads、var/cache、var/home-static) |
| 可选 | HTTPS 证书、CDN(Cloudflare 等) |
安装步骤
- 下载发布包,解压到站点根目录(docroot),确认
index.php、core/、themes/、plugins/在同一层。 - 建库:
CREATE DATABASE yecha DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - 复制
config.inc.php.example为config.inc.php,填写数据库与SECRET(见配置项)。 - 浏览器打开站点根目录,进入一次性安装向导;若已手动建表,访问
/install/会提示「已安装」。 - 配置伪静态(Nginx 最小可用):
location / { try_files $uri $uri/ /index.php?$query_string; }
location ~ ^/(var|data|install|tools|tests|core|config\.inc\.php) { deny all; }
location ~* \.(bak|orig|old|save|swp|tmp|sql|gz|log)$ { deny all; }- 安装完成立即:改管理员口令、删除或锁死
install/目录、确认core/不可直出。
目录权限
chown -R www:www /www/wwwroot/yecha.org
find /www/wwwroot/yecha.org -type d -exec chmod 755 {} \;
find /www/wwwroot/yecha.org -type f -exec chmod 644 {} \;
chmod -R 775 /www/wwwroot/yecha.org/uploads /www/wwwroot/yecha.org/var常见安装错误
| 现象 | 原因 | 处理 |
|---|---|---|
打开 /install/ 得 403 | 伪静态拒绝规则把安装目录也拦了 | 把 install 从拒绝规则中拆出单独一条,不要加 ^~ |
整站 500,日志报 Unknown column 'c.words' | 1.0.0 内核列表按 ye_contents.words 取字数,旧库无该列 | ALTER TABLE ye_contents ADD COLUMN words INT UNSIGNED NOT NULL DEFAULT 0; 再回填 CHAR_LENGTH(content) |
首页空白 / 模板不存在 | 主题缺 views/landing.php 或 views/layout.php | 后台切回默认主题 yecha,或补齐模板 |
| 页面 404,后台正常 | 伪静态未生效 | 按上面 Nginx 规则配置并 nginx -t && nginx -s reload |
| 上传图片失败 | uploads 不可写 | 按「目录权限」修正属主 |
升级
升级前备份
B=/root/backup/$(date -u +%Y%m%dT%H%M%SZ); mkdir -p "$B"
mysqldump --single-transaction --routines yecha | gzip > "$B/yecha.sql.gz"
tar czf "$B/site.tar.gz" -C /www/wwwroot yecha.org --exclude='uploads/*' --exclude='var/cache/*'
cp -a /www/wwwroot/yecha.org/config.inc.php "$B/config.inc.php.orig"升级步骤
- 覆盖内核文件(
index.php、core/、admin/、lang/),保留config.inc.php、uploads/、var/。 - 覆盖或新增主题/插件目录;同名主题建议先备份再覆盖。
- 插件迁移在插件启用时自动执行(内核
Upgrade::apply(),幂等,重复执行无副作用)。 - 清缓存并重建首页静态件(见缓存与静态件)。
升级后自检
- 抽样 10 页是否 200,5xx 是否为 0;
- 后台能登录、能保存设置;
- 主题/插件列表条数与目录数一致;
/sitemap.xml、/feed正常;- 多语站抽查
/en/与/en/category/…/。
回滚
# 库
gunzip -c /root/backup/<时间>/yecha.sql.gz | mysql yecha
# 文件
tar xzf /root/backup/<时间>/site.tar.gz -C /www/wwwroot主题开发
目录结构
themes/<id>/
theme.json # 元数据与后台可调设置
style.css # 主题样式
views/
layout.php # 整页外壳(必须)
landing.php # 首页门户版式(可选,home.landing=1 时启用)
landing-en.php # 分语言首页(可选,/en/ 时优先)
404.php
partials/ # list / post / page / search / archives …
logo.png / favicon.pngtheme.json
| 字段 | 说明 |
|---|---|
| name / version / description | 显示名、版本、简介(后台与在线主题页读取) |
| requires_core | 依赖的内核版本 |
| author / license | 作者与许可 |
| settings | 后台可调项数组:key / type(select、color、number、checkbox) / label / def / opts |
| home | 设为 landing 时首页走门户版式 |
最小可用主题
themes/hello/theme.json:
{ "name": "Hello", "version": "0.1.0", "requires_core": "1.0.0", "description": "最小示例主题" }themes/hello/views/layout.php:
<!DOCTYPE html><html lang="<?= e($htmlLang ?? 'zh-CN') ?>"><head>
<meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title><?= e($title) ?></title>
<link rel="stylesheet" href="<?= e(View::asset('style.css')) ?>">
</head><body>
<header><?php foreach (Nav::list('top', Lang::short()) as $n): ?>
<a href="<?= e($n['href']) ?>"<?= $n['active'] ? ' class="active"' : '' ?>><?= e($n['label']) ?></a>
<?php endforeach; ?></header>
<main><?= $main ?></main>
<aside><?= $side ?></aside>
</body></html>模板与变量
$title页面标题、$main正文 HTML、$side侧栏 HTML、$htmlLang语言;- 常用函数:
e()转义、__()语言包、site_label()站点名、theme_opt('key','默认')主题设置、Nav::list('top'|'foot')导航、Poly::termUrl()/termName()多语术语; - 资源用
View::asset('style.css')输出带版本号的 URL(?v=mtime),改样式不用手工改版本。
调试与发布
- 目录放进
themes/,后台「主题」即可见并切换; - 切换后清页面缓存、重建首页静态件(见缓存与静态件);
- 缺模板时内核会回落到默认主题
yecha并在var/log/php-error.log留记录,不静默; - 发布前逐套
php -l,并在390窄屏检查导航折叠。
插件开发
目录结构
plugins/<id>/
plugin.php # 清单(返回数组)
boot.php # 启用时注册钩子(register_file)
admin.php # 后台页(admin_file/admin_fn)
page.php # 前台独立页(page_file/page_fn)
migrations/ # 幂等迁移 *.php 或 *.sqlplugin.php 清单
| 字段 | 说明 |
|---|---|
| id / name / ver / desc / author / license | 基本信息,在线插件页直接读取 |
| requires.core | 依赖内核版本 |
| toggle | 是否允许停用 |
| tables | 自有表名(安装/卸载据此建表与清理) |
| pages | 前台页:[['slug'=>'hello','title'=>'示例']],路由 /<slug> |
| blocks | 侧栏块:[['id'=>'hello','label'=>'示例块']] |
| register_file | 启用时 include 的文件(通常 boot.php) |
| admin_file / admin_fn | 后台页文件与渲染函数 |
| page_file / page_fn | 前台页文件与渲染函数,函数返回 ['html'=>…, 'title'=>…] |
| uninstall | ['tables'=>[], 'options'=>[], 'like'=>[]] |
最小插件
plugins/hello/plugin.php:
<?php
return [
'id' => 'hello', 'name' => '示例插件', 'ver' => '0.1.0',
'desc' => '最小插件示例', 'author' => 'YeCha', 'license' => 'MIT',
'requires' => ['core' => '1.0.0'], 'toggle' => true,
'pages' => [['slug' => 'hello', 'title' => '示例页']],
'register_file' => 'boot.php',
'page_file' => 'page.php', 'page_fn' => 'hello_page',
];plugins/hello/boot.php:
<?php
Hooks::on('front.head', function (array $p): array { return $p; }, 10);plugins/hello/page.php:
<?php
function hello_page(string $slug): array {
return ['html' => '<h1>Hello</h1><p>来自示例插件。</p>', 'title' => '示例页 · ' . site_label()];
}放置后在后台「插件」启用即生效;前台访问 /hello。
路由、权限与迁移
- 多级路径:内核把
/<slug>/…交给插件页,子路径在$GLOBALS['YC_PLUGIN_PATH']中; - 后台页需管理员会话;表单必须带
Csrf::field()并Csrf::check(); - 迁移写在
migrations/,用CREATE TABLE IF NOT EXISTS/ 先查后建,保证幂等; - 停用只停止注册,数据保留;卸载按
uninstall清理。
配置项
config.inc.php
| 常量 | 说明 |
|---|---|
| DB_HOST / DB_PORT / DB_NAME / DB_USER / DB_PASS | 数据库连接 |
| DB_PREFIX | 表前缀,默认 ye_ |
| SECRET | 站点密钥:会话、加密(AI Key 等)都用它;换掉会让已加密的密钥失效 |
| TZ | 时区,默认 Asia/Shanghai |
| SITE_LANG | 默认界面语言,如 zh_CN |
| DEBUG | 生产必须 false;true 会把错误显示到页面 |
站点选项(options 表)
| 选项 | 说明 |
|---|---|
| site.name / site.name_en | 站点中文名 / 英文名(/en/ 下显示英文名) |
| site.subtitle / site.subtitle_en | 副标题 / 英文副标题 |
| site.languages / site.default_lang | 启用语言与默认语言,如 ["zh","en"] |
| theme.default / theme.options | 当前主题与主题设置 |
| home.landing | 1 = 首页使用主题的门户版式 |
| nav.hide_top / nav.hide_foot / nav.custom | 顶部/页脚隐藏项与自定义导航 |
| stats.head / stats.foot | 统计代码位(留空即零外发) |
| market.source | 云市场清单地址,留空 = 本站 var/market/manifest.json |
密钥与敏感信息
- 不要把任何密钥写进主题/插件源码或仓库;AI、短信、支付等密钥一律在后台填写,入库前用
SECRET加密,界面不回显明文; SECRET只存在config.inc.php(权限 640、属主 root:www),不进版本库;- 轮换
SECRET前先导出并重新录入受影响的密钥,否则旧密文无法解密; - 日志、报错页、导出文件都不得包含密钥;
DEBUG=true只允许在本机临时使用。
缓存与静态件
| 位置 | 作用 | 何时清理 |
|---|---|---|
var/cache/pages | 全页缓存 | 改内容/主题/菜单后 |
var/cache/blocks | 侧栏与区块缓存 | 改侧栏/插件后 |
var/home-static/ | 首页烘焙件(含 /en/) | 改首页/主题/统计代码后 |
# 清缓存(也可后台「工具 → 清缓存」)
php -r 'chdir("/www/wwwroot/yecha.org"); require "config.inc.php"; require "core/bootstrap.php"; Cache::flush("pages"); Cache::flush("blocks");'
# 重建首页静态件
curl -s -H 'Host: yecha.org' https://127.0.0.1/ >/dev/null # 或后台「首页生成静态 → 立即生成」常见问题
/en/category/xxx/ 返回 500?
旧库缺 ye_contents.words 列。按常见安装错误加列并回填,然后清页面缓存。
换了主题,首页看起来没变?
首页有烘焙静态件(var/home-static/index.html 与 en/index.html)。删除或重新生成后才会按新主题渲染。
后台登录后马上跳回登录页?
多为 HTTPS 判定与会话 Cookie 不一致:确认源站 fastcgi_param HTTPS on、site.url 与访问域名一致,并清一次浏览器 Cookie。
多语内容不显示?
确认 poly 插件已启用、site.languages 含该语言、且译文状态为 publish;术语名/别名在后台「多语言」维护。
云市场安装失败?
只接受 https 且强制 SHA-256 校验;检查包结构与 plugin.php/theme.json 是否齐全,PHP 是否全部 php -l 通过。
如何只保留官网、关闭博客?
启用 site 插件并在后台切到官网模式;博客文章改走 301,插件详情与文档页不受影响。需要恢复时一键切回博客模式。
如何迁移站点?
导出库 + 打包站点文件(含 uploads/),在新机按安装配好环境、导入库、改 config.inc.php,最后清缓存并重建静态件。