Hope CMS 文档
Hope CMS(希望CMS)是一款面向中文站长与 PHP 开发者的轻量开源内容管理系统:安装快、结构清楚、主题/插件零侵入扩展,适合个人博客、工作室站、资讯站与付费资源站。
请仅从官方域名下载安装包,其他来源存在安全风险。
命名说明
| 名称 |
用途 |
| Hope CMS |
程序主名称(文档、导航) |
| 希望CMS |
中文副名称 |
你能用它做什么
| 场景 |
说明 |
| 个人 / 技术博客 |
Markdown 写作、分类标签、评论、SEO |
| 企业 / 工作室官网 |
独立页面模板、主题切换、侧栏组件 |
| 资讯 / 内容站 |
多作者角色、媒体库、伪静态链接 |
| 付费资源 / 会员站 |
个人中心、余额充值、支付网关(配合 Shop 等主题) |
| 小程序 / 前后端分离 |
REST API(API Key、限流、CORS 视配置而定) |
核心能力
- 内容:Markdown(Editor.md)、分类 / 标签 / 封面 / 别名 / 置顶 / 阅读密码
- 用户:管理员 / 编辑 / 作者 / 访客;后台模块权限
- SEO 与链接:站点 / 文章 / 分类 / 标签 TDK;动态 / 伪静态 / index.php 三种链接模式
- 扩展:挂载点(
hope_listen / hope_emit)、主题、插件、侧边栏组件
- 媒体与评论:附件库、评论审核、验证码、邮件通知
- 个人中心:资料、余额、邀请奖励、在线支付(微信 / 支付宝等)
- 运维:备份导入、更新缓存、SMTP、多语言后台、AI 工作台(可选)
- 数据层:链式查询(
HopeDb);插件在 callback_init 内建表
官方示例: 主题 content/theme/default/ · 插件 content/plugin/tips/
官网主题(本主题 hopecms)还可提供:用户论坛、站内开发文档、主题生成器等。
环境一览
| 项目 |
要求 |
| PHP |
7.0+(推荐 8.0+;建议同时验证 8.x) |
| 数据库 |
MySQL 5.6+ / MariaDB 10.3+(mysqli 或 pdo_mysql) |
| Web |
Apache / Nginx(IIS 需 URL Rewrite) |
| 扩展 |
建议 mbstring、json、curl、gd/imagick、openssl |
详细步骤见 安装指南。
文档导航
按阅读顺序:
| 分组 |
章节 |
内容 |
| 入门 |
安装指南 |
上传、安装向导、安全加固 |
| 入门 |
升级与更新 |
覆盖升级、插件/主题回调、更新缓存 |
| 入门 |
常见问题 |
安装排障、旧版兼容、开发疑问 |
| 入门 |
目录说明 |
content/ 与 system/ 结构总览 |
| 开发基础 |
开发准备工作 |
目录、常量、请求流程、常用 API |
| 开发基础 |
挂载点手册 |
HopeHooks 全表与 hope_listen / hope_emit |
| 开发基础 |
数据库与 SQL |
HopeDb、建表、MetaStorage |
| 主题 |
主题开发指南 |
目录结构、模板、CSF 设置、生命周期 |
| 主题 |
侧边栏开发说明 |
widgets 注册与渲染 |
| 插件 |
插件开发指南 |
结构、钩子、设置页、前台页、发布清单 |
| 接口 |
伪静态与路由 |
链接模式、服务器配置、插件路由 |
| 接口 |
API 开发文档 |
REST、个人中心 API、鉴权 |
| 关于 |
联系我们 |
官方渠道与反馈方式 |
目录总览见 目录说明。
二次开发原则
- 不要改
system/ 业务逻辑(升级会覆盖);扩展放在 content/theme/ 与 content/plugin/
- 主题负责皮肤与布局;跨主题能力做成插件
- 站点标题 / 副标题 / SEO / 版权走后台「设置」(
Settings::get('sitename') 等)
- 输出用户内容使用
htmlspecialchars;数据库用 HopeDb,禁止拼接不可信 SQL
官方域名
软件许可证
Hope CMS(希望CMS)核心代码按 Apache License 2.0 发布。捆绑的第三方库以其目录内说明为准。
安装指南
从拿到安装包到站点可访问,通常只需:上传 → 运行向导 → 加固安全。
环境要求
| 项目 |
要求 |
| PHP |
7.0+(推荐 8.0+;建议同时验证 7.4 / 8.x) |
| 数据库 |
MySQL 5.6+ / MariaDB 10.3+(mysqli 或 pdo_mysql) |
| Web |
Apache / Nginx(IIS 需 URL Rewrite) |
| 扩展 |
建议:mbstring、json、curl、gd 或 imagick、openssl |
目录需可写:content/upload/、content/cache/(Linux 常见 755/775,属主为 Web 用户)。
三步安装
第一步:上传程序
- 从 官方下载页 获取最新安装包并解压
- 将全部文件上传到网站根目录(虚拟主机常见
public_html / wwwroot),或子目录
- 确认
content/cache/、content/upload/ 可写
子目录安装时,后续需正确配置站点 URL,伪静态还要改 RewriteBase / Nginx 前缀。
第二步:运行安装向导
浏览器访问:
http://你的域名/install.php
按向导填写:
| 项 |
说明 |
| 数据库主机 |
多为 localhost |
| 库名 / 用户 / 密码 |
事先在面板或 phpMyAdmin 建空库 |
| 表前缀 |
默认一般可用;同库多套程序时请改前缀 |
| 管理员账号 |
站点最高权限,密码请足够复杂 |
完成后会写入 content/cache/install.lock,并尽量将 install.php 重命名为 install.php.disabled。
第三步:删除安装入口并登录
- 立即删除或重命名
install.php(若仍存在)
- 访问前台域名确认主题正常
- 后台默认入口:
admin.php(见下文安全加固)
安装后必做
- 登录后台
- 重命名后台入口:将根目录
admin.php 改为不易猜测的文件名(如 manage_x8k2.php),并更新书签
仍使用 admin.php 时,示例插件「小贴士」会在后台首页提示安全风险
- 外观 → 主题:启用所需主题;有
settings.php 时可配置外观
- 设置 → 站点信息 / SEO:站点标题、副标题、描述、版权(主题通过系统配置读取)
- 设置 → 链接:选择动态 / 伪静态;伪静态需配置服务器,见 伪静态与路由
- 插件 → 插件管理:按需启用(支付、OAuth 等)
- 按需配置 SMTP、支付网关
- 执行一次 设置 → 更新缓存
重装
- 备份数据库与
content/upload/
- 删除
content/cache/install.lock
- 如程序要求,设置环境变量
HOPE_ALLOW_REINSTALL=1
- 必要时从
install.php.bak 恢复 install.php
- 重新访问安装向导
重装会覆盖库表数据,生产环境务必先备份。
常见问题
打开 install.php 空白 / 报错
- 检查 PHP 版本与必装扩展
- 查看
content/cache/error.log 或 Web 服务器错误日志
- 确认未误删
system/ 或 content/ 关键文件
提示目录不可写
- 调整
content/cache、content/upload 权限与属主
- 部分主机禁止
777,优先用属主可写的 755/775
安装完成仍可访问 install.php
- 手动删除或重命名
install.php
- 确认存在
content/cache/install.lock
子目录安装后样式 / 链接错乱
- 后台核对站点 URL(含路径与尾斜杠)
- 伪静态时修正
RewriteBase 或 Nginx location 前缀
- 更新缓存后再测
后台无法登录
- 确认使用的是重命名后的入口文件
- 清除浏览器 Cookie 后重试
- 检查数据库用户表管理员是否安装成功
前台 500 / 白屏
- 开启开发者模式排查(见 开发准备工作)
- 确认
system/config.php 数据库信息正确
- PHP 版本过低或缺少扩展时,安装后也可能在个别页面报错
从旧版本升级
已有站点不要再跑安装向导。覆盖文件、插件字段迁移与缓存刷新见 升级与更新。
开发环境与目录约定见 开发准备工作。
升级与更新
本文说明 Hope CMS 程序覆盖升级、插件/主题升级、数据库字段迁移与站点缓存刷新。
适用场景速查
| 场景 |
推荐做法 |
详见 |
| 覆盖更新核心包 |
备份 → 覆盖 system/ 等 → 更新缓存 |
程序升级 |
| 插件版本迭代加字段 |
callback_up() + 幂等 schema |
插件更新 |
| 主题启用时建表 / 初始化 |
主题 callback.php 的 callback_init() |
主题更新 |
| 改菜单/标签/分类名后前台未变 |
后台「更新缓存」 |
更新缓存 |
| 仅刷新某类缓存 |
$SNAP->refresh([...]) |
更新缓存 |
覆盖更新可能改写 system/。业务扩展请写在 content/plugin/、content/theme/,勿改核心后指望下次升级保留。
升级前建议:备份数据库 + 备份 content/upload/ +(可选)整站文件快照。
程序升级
- 后台导出或 mysqldump 备份数据库
- 备份整站(至少
system/、content/、入口 PHP)
- 用新版覆盖文件;保留
system/config.php 与本地已改配置
- 保留
content/upload/、content/cache/install.lock、自定义主题/插件
- 登录后台执行 更新缓存;若从 1.0.4 等旧版覆盖升级,可再点 清理旧版残余(或依赖在线升级自动清理)
- 抽查:首页、文章、登录、后台写文章、已启用插件
若发行说明要求执行 SQL 或一次性脚本,按说明操作;不要重复跑 install.php。
升级后若旧结构主题异常,见 常见问题 · 旧版兼容。
清理旧版残余文件
从 HopeCMS 1.0.4 覆盖升级后,旧的 controller / model、base.php、旧类名 lib 等文件可能仍留在 system/。
逻辑见 system/lib/legacy_cleanup.php:
- 在线升级成功后自动执行
- 也可在后台 设置 → 更新缓存 旁手动「清理旧版残余」
仅删除白名单路径,不会动 config.php、主题、插件、上传目录。
插件更新
插件目录:content/plugin/{插件名}/。
生命周期
| 回调 |
时机 |
建议 |
callback_init() |
启用时 |
建表、初始化 MetaStorage、幂等 schema |
callback_up() |
更新时 |
再跑同一 schema 升级函数 |
callback_rm() |
删除时 |
MetaStorage::deleteAllName('YES');按需 HopeSql::dropTables |
启用顺序:加载 {插件}_callback.php → callback_init()(不会自动执行 install.sql)。
推荐写法
// tips_callback.php
function callback_up() {
callback_init();
}
function callback_init() {
// 有表时:myplugin_upgrade_schema();
}
function callback_rm() {
MetaStorage::getInstance('tips')->deleteAllName('YES');
}
有表插件将 CREATE + ALTER 放在同一升级函数。完整示例见 数据库与 SQL。
字段升级原则
- 建表用
CREATE TABLE IF NOT EXISTS
- 新字段先
SHOW COLUMNS 再 ALTER(可重复执行)
callback_init 与 callback_up 调用同一函数
- 禁止改核心表结构(
article、user、option 等)
主题更新
- 建表 / 初始化:主题根目录
callback.php 的 callback_init()(删除时 callback_rm())
- CSF
settings.php 增删字段后,读取必须带默认值:hope_option('key', 'default') / _hope()
- 新增
pages/*.php 页面模板后:后台新建页面并选择该模板
$prefix(如 default_options)不要随意改名,否则已保存配置失效
主题结构见 主题开发指南。
更新缓存
后台:设置 → 数据 → 更新缓存(或系统设置中的「更新缓存」入口)。
会做什么
全量 SnapshotBank::refresh()(全局实例常为 $SNAP),重建包括但不限于:
options、user、sta、comment、tags、category、link、menu、newlog、record、logalias、logcategory、logtags
并调用 Settings::resetRoutingTableCache() 清空伪静态路由表内存缓存(保存「设置 → 链接」时也会重置)。
菜单标题同步
刷新 menu 时会同步文章 / 页面 / 分类 / 标签类型菜单项标题为来源最新名称;自定义链接名不受影响。
改了标签名、分类名或文章标题后,点一次「更新缓存」即可让导航跟上。
代码中局部刷新
global $SNAP;
$SNAP = SnapshotBank::getInstance();
$SNAP->refresh(); // 全量
$SNAP->refresh(['tags', 'menu', 'category']); // 指定
$SNAP->refreshPosts(); // 文章相关常用组合
缓存文件在 content/cache/*.php;请确保目录可写。
开发自检清单
- [ ] 插件 / 主题
Version 头信息已递增
- [ ] 新表与新字段在幂等升级函数中(
callback_init / callback_up)
- [ ]
callback_rm 已清理 MetaStorage;有表则明确是否 DROP
- [ ] 未改核心表结构与
system/ 业务文件
- [ ] 主题新配置均有默认值;
$prefix 未误改
- [ ] 升级前已备份;升级后已「更新缓存」并抽查前台
相关文档
常见问题
集中说明安装、升级与二次开发中的常见疑惑。旧主题 / 旧插件兼容说明只在本文维护,其它章节不再重复。
相关:安装指南 · 升级与更新 · 主题开发指南 · 插件开发指南
安装与后台
打开 install.php 空白 / 报错
- 检查 PHP 版本与必装扩展(见 安装指南)
- 查看
content/cache/error.log 或 Web 服务器错误日志
- 确认未误删
system/ 或 content/ 关键文件
安装后无法进后台
- 确认已删除或重命名根目录
install.php
- 入口默认为
admin.php;若已改名,请使用新文件名
- 清除浏览器缓存后重试
前台样式丢失 / 链接异常
- 后台 设置 → 更新缓存
- 检查「设置 → 链接」模式是否与服务器伪静态配置一致(见 伪静态与路由)
升级后仍看到旧报错 / 旧类文件
从 1.0.4 覆盖升级后,可用后台 设置 → 清理旧版残余(system/lib/legacy_cleanup.php)删除废弃的 controller/model 等文件;在线升级成功时也会自动清理。
旧版兼容(legacy_compat)
内核只认主题与 API 的新规范。需要继续跑旧结构主题,或仍使用旧函数/类名的第三方插件时,启用插件 「旧版兼容」(content/plugin/legacy_compat/)。
default、hopecms 等已迁移主题,以及已改用现行 API 的插件,不必启用。
何时启用
| 场景 |
是否需要 |
zib / Shop / fly 等仍用 header.php、log_list.php、page/、user/ 的主题 |
需要 |
第三方插件仍写 addAction / Option / View / Cache::readCache 等 |
需要 |
| 仅用已迁移主题 + 现行 API 插件 |
不必 |
怎么启用
- 后台 插件 → 插件管理 启用「旧版兼容」
- 启用时会自动排到
active_plugins 最前,保证其它旧插件加载前垫片已就绪
- 再启用或切换旧结构主题;执行一次 更新缓存
升级程序后若旧主题突然空白或找不到模板:优先检查本插件是否仍启用。
旧主题路径对照
| 新 |
旧(需启用本插件) |
head.php / foot.php |
header.php / footer.php |
archive.php / single.php |
log_list.php / echo_log.php |
archive_* / single_* |
log_list_* / echo_log_* |
author.php |
log_author.php |
functions.php / settings.php / hooks.php |
module.php / options.php / plugins.php |
pages/ / account/ |
page/ / user/ |
widgets/config.php、widget-*.php |
side_config.php、side_*.php |
Handler 仍可使用逻辑名 header、log_list、echo_log 等,内核映射到新文件;旧物理文件由本插件注入候选路径。
旧插件 API 对照(节选)
| 旧 |
现行 |
addAction / doAction / doMultiAction |
hope_listen / hope_emit / hope_emit_pipe |
$hopeHooks |
$hopeEvents |
Option |
Settings |
View::getView |
PageComposer::themePath |
Url::log / Url::sort |
SiteUrl::post / SiteUrl::category |
Cache + readCache / updateCache |
SnapshotBank + read / refresh |
$CACHE |
Cache 代理($SNAP 仍为 SnapshotBank) |
Storage / Database / LoginAuth |
MetaStorage / HopeDb / AuthSession |
PLUGIN_PATH / TPLS_PATH |
HOPE_PLUGINS_PATH / HOPE_THEMES_PATH |
完整对照表:content/plugin/legacy_compat/naming_map.php。插件说明:content/plugin/legacy_compat/README.md。
新项目要不要写旧名?
不要。新主题按 head.php / archive.php / pages/ / account/ / widgets/ 规范编写;新插件直接使用 hope_listen、Settings、HopeDb 等现行 API。
主题与插件开发
主题设置页不出现
主题根目录需有 settings.php(CSF)。确认当前主题已启用,并刷新后台菜单。
侧边栏组件不显示
- 确认
widgets/config.php 已注册对应 side_* key
- 确认存在
widgets/widget-{name}.php
- 换主题后到 外观 → 侧边栏 重新勾选组件
插件启用后无效果
- 确认入口文件头信息与目录名一致
- 钩子是否写在入口或
*_lib.php 且已被 require
- 查看是否与其它插件互斥;需要时检查
content/cache/error.log
更多
目录总览见 目录说明。反馈渠道见 联系我们。
目录说明
Hope CMS 根目录只保留两个文件夹:content/(内容区)与 system/(程序区),外加少量入口文件。
相关:开发准备工作 · 常见问题
根目录
hope/
├── index.php # 前台入口 → system/bootstrap.php
├── admin.php # 后台入口 → system/bootstrap.php
├── install.php # 安装向导
├── content/ # 主题、插件、上传、缓存等可变内容
└── system/ # 内核、业务、后台逻辑、公共库
| 文件 / 目录 |
说明 |
index.php |
前台统一入口 |
admin.php |
后台统一入口 |
install.php |
首次安装(库表 SQL 内嵌) |
content/ |
站点内容与扩展(升级主题/插件主要改这里) |
system/ |
程序核心(一般升级程序改这里) |
content/ — 内容区
content/
├── theme/ # 前台主题
├── plugin/ # 插件
├── admin/ # 后台视图(HTML / CSS / JS)
├── upload/ # 用户上传文件
├── cache/ # 运行时缓存(配置、分类、统计等)
├── lang/ # 语言包
├── logs/ # 日志
├── static/ # 静态资源
└── theme_ref/ # 主题参考材料(非运行必需)
| 目录 |
作用 |
theme/ |
可切换的前台主题,当前主题由站点配置决定 |
plugin/ |
可启用/停用的插件 |
admin/ |
后台界面模板与静态资源,与 system/admin 控制器配合 |
upload/ |
媒体与附件存储 |
cache/ |
PHP 数组缓存文件,加速读写 |
lang/ |
多语言文案 |
logs/ |
运行/审计日志 |
static/ |
公共静态文件 |
theme_ref/ |
参考或备份主题资源,默认不参与运行 |
站内开发文档位于当前主题 content/theme/hopecms/docs/。
system/ — 程序区
system/
├── Hope/ # 内核命名空间:启动、路由、配置、事件
├── app/ # 业务分层:handler / store / service
├── admin/ # 后台控制器
├── lib/ # 公共库
├── options/ # 主题选项框架(Codestar)
├── deploy/ # 部署示例(如 nginx)
├── bootstrap.php # 内核引导(前台 / 后台共用)
├── config.php # 数据库等站点配置
└── checkcode.php # 验证码兼容入口
system/Hope/ — 内核
system/Hope/
├── Foundation/ # Application、Paths、ClassLoader、path_constants
├── Bootstrap/ # RuntimeBoot 启动编排
├── Http/ # FrontRouter、Request、RouteMatch
├── Config/ # Settings 站点配置
├── Runtime/ # SnapshotBank 快照缓存
├── Presentation/ # PageComposer 视图路径解析
└── Event/ # HookBus 事件总线
system/app/ — 业务分层
| 目录 |
角色 |
示例 |
handler/ |
前台请求处理 |
Post_Handler、Category_Handler、User_Handler |
store/ |
数据访问 |
Post_Store、Comment_Store、User_Store |
service/ |
领域服务 |
UserService、NoticeService、MediaService |
system/admin/ — 后台控制器
按功能拆分,例如:article.php、article_edit.php、comment.php、setting.php、theme.php、plugin.php 等。
视图在 content/admin/。
system/lib/ — 公共库
lib/
├── auth/ # 登录会话、密码、授权
├── database/ # HopeDb / HopeMysqli / 查询与元存储
├── http/ # 请求输入、站点 URL、JSON 输出、HTTP 客户端
├── mail/ # 邮件发送
├── payment/ # 支付通道与收银台
├── captcha/ # 验证码与字体
├── markdown/ # Markdown 解析
├── support/ # 语言、异常等支撑
├── view/ # 侧栏日历、应用商店视图 helpers
├── common.php # 全局辅助函数
├── hooks.php # 钩子常量
├── sidebar.php # 侧栏注册与渲染
└── upgrade_helper.php
其他
| 路径 |
说明 |
system/options/ |
主题选项 UI 框架(CSF) |
install.php(根目录) |
安装向导;库表 SQL 已内嵌于 hope_install_schema_template() |
system/deploy/ |
部署配置示例 |
content/plugin/legacy_compat/naming_map.php |
旧命名 → 新命名对照(说明见 常见问题) |
system/config.php |
DB_*、表前缀、密钥等 |
请求流程
前台
index.php
→ system/bootstrap.php
→ Application 启动
→ FrontRouter 匹配路由
→ app/handler/*
→ content/theme/<当前主题>/
后台
admin.php
→ system/bootstrap.php(加载内核)
→ system/admin/globals.php
→ system/admin/<act>.php
→ content/admin/<act>.php(视图)
记忆口诀
content:装什么(主题、插件、文件、缓存)
system:怎么跑(内核、业务、后台、公共库)
二次开发时:改界面与扩展优先看 content/;改路由、保存逻辑、权限与数据层优先看 system/。
开发准备工作
Hope CMS 支持主题与插件扩展。本文说明本地环境、目录约定、请求流程与常用 API,便于二次开发。
相关:挂载点手册 · 主题开发指南 · 插件开发指南 · 数据库与 SQL
开发环境
| 项目 |
要求 |
| PHP |
7.0+(建议同时测试 8.0 / 8.3) |
| MySQL |
5.6+ / MariaDB 10.3+ |
| Web |
Apache / Nginx |
| 扩展 |
mysqli 或 pdo_mysql;建议 mbstring、json、curl |
| 浏览器 |
Chrome / Edge 等现代浏览器 |
将站点根目录(含 index.php)设为 Web 根目录,并确保 content/upload/、content/cache/ 可写。
目录结构
根目录只保留 content/(内容区)与 system/(程序区),外加入口文件:
hope/ # 站点根(HOPE_ROOT)
├── index.php # 前台入口
├── admin.php # 后台入口
├── install.php # 安装向导(库表 SQL 内嵌)
├── system/ # 内核(升级会覆盖,勿直接改业务)
│ ├── Hope/ # Foundation / Bootstrap / Http / Config / Runtime / Presentation / Event
│ ├── app/
│ │ ├── handler/ # 前台请求处理(*_Handler)
│ │ ├── store/ # 数据访问(*_Store)
│ │ └── service/ # 领域服务
│ ├── admin/ # 后台控制器(与 content/admin 视图配对)
│ ├── lib/ # 公共库(common.php、hooks.php、sidebar.php、database/、http/…)
│ ├── options/ # 主题选项框架(CSF)
│ ├── bootstrap.php # 内核引导
│ └── config.php # 数据库、AUTH_KEY 等
└── content/ # ★ 开发者主要工作区
├── theme/ # 主题
├── plugin/ # 插件
├── admin/ # 后台 HTML / CSS / JS
├── upload/ # 用户上传
├── cache/ # 运行时缓存
├── lang/ # 语言包
└── logs/ # 日志
记忆口诀: content 装什么;system 怎么跑。
完整说明见 目录说明。
快速上手:示例插件
官方示例: content/plugin/tips/
- 复制
tips 目录并改名,修改 Plugin Name 与函数前缀
- 后台 插件 → 插件管理 启用
- 启用时加载
{插件}_callback.php 并调用 callback_init()
// tips.php
hope_listen('adm_main_top', 'tips_render_admin_banner');
hope_listen('adm_head', 'tips_enqueue_admin_css');
// tips_callback.php
function callback_init() { /* 启用即生效 */ }
function callback_rm() {
MetaStorage::getInstance('tips')->deleteAllName('YES');
}
完整说明见 插件开发指南。
快速上手:示例主题
官方示例: content/theme/default/
- 复制
default 为新主题目录,修改 head.php 元信息与 settings.php 的 $prefix
- 在
pages/ 下新建页面模板,首行写 /*@name 关于我们*/
- 后台 页面 → 新建页面,选择对应模板
- 布局参考同主题
head.php / foot.php
<?php
/*@name 关于我们*/
defined('HOPE_ROOT') || exit('access denied!');
?>
<section class="about">
<h1><?= htmlspecialchars((string) Settings::get('sitename')) ?></h1>
</section>
<?php include PageComposer::themePath('footer'); ?>
文件清单、CSF、模板变量见 主题开发指南。
请求流程
| 入口 |
流程 |
前台 index.php |
bootstrap.php → Application → 加载插件 → include 主题 hooks.php → hope_emit('init') → FrontRouter → *_Handler → 主题模板 |
后台 admin.php |
bootstrap.php → system/admin/globals.php 按 act 分发 → system/admin/{act}.php → content/admin/{act}.php |
| REST API |
?rest-api=方法名 → API Handler → JsonOut::ok() / JsonOut::error() |
| 插件设置页 |
{后台入口}?act=plugin_set&plugin=插件名 → {插件}_setting.php 的 plugin_setting_view() |
插件可通过 HopeHooks::ROUTING_REGISTER 注册前台伪静态路由,见 伪静态与路由。
常用常量
| 常量 |
说明 |
HOPE_ROOT |
站点根目录绝对路径(含尾 /) |
DB_PREFIX |
表前缀(system/config.php) |
SITE_URL |
站点 URL(含末尾 /) |
THEME_PATH / THEME_URL |
当前主题物理路径 / URL |
HOPE_THEMES_PATH / HOPE_THEMES_URL |
主题根目录 |
HOPE_PLUGINS_PATH / HOPE_PLUGINS_URL |
插件根目录 |
ADMIN_TEMPLATE_PATH |
后台视图目录(content/admin/) |
ISLOGIN / UID / ROLE |
登录态、用户 ID、角色 |
路径常量:HOPE_PATH_APP、HOPE_PATH_STORE、HOPE_PATH_HANDLER、HOPE_PATH_SERVICE、HOPE_PATH_ADMIN、HOPE_PATH_LIBRARY。
用户角色
| 常量 |
值 |
典型权限 |
ROLE_ADMIN |
admin |
全部后台权限 |
ROLE_EDITOR |
editor |
管理内容与评论 |
ROLE_WRITER |
writer |
管理自己的文章 |
ROLE_VISITOR |
visitor |
前台只读 |
插件后台页由核心保障管理员权限;独立 AJAX 需自行校验:
if (!AuthSession::isLogin() || ROLE !== ROLE_ADMIN) {
JsonOut::authError('权限不足');
}
挂载点(速览)
hope_listen(HopeHooks::ADM_HEAD, 'tips_enqueue_admin_css');
hope_listen(HopeHooks::ADM_MAIN_TOP, 'tips_render_admin_banner');
hope_emit(HopeHooks::INDEX_HEAD);
| 函数 |
行为 |
hope_listen($hook, $callback) |
注册 |
hope_emit($hook, ...) |
执行全部回调 |
hope_emit_once($hook, $input, &$ret) |
仅第一个,可改 $ret |
hope_emit_pipe($hook, $input, &$ret) |
链式变换 $ret |
hope_unlisten / hope_has_listener |
移除 / 判断 |
完整列表见 挂载点手册。常量源码:system/lib/hooks.php。
配置与选项
系统设置
$sitename = Settings::get('sitename');
Settings::updateOption('apikey', $key);
Settings::updateOption('is_openapi', 'y');
主题配置(CSF)
$color = hope_option('primary_color', '#3b82f6');
$layout = _hope('site_layout', 'double');
站点标题等请用 Settings::get('sitename') / hope_site_name()。
插件私有配置
$storage = MetaStorage::getInstance('tips');
$storage->setValue('config', ['foo' => 'bar'], 'array');
$config = $storage->getValue('config');
$storage->deleteAllName('YES'); // 卸载时
输入输出
$id = RequestInput::getIntVar('id');
$page = RequestInput::getIntVar('page', 1, 1);
$name = RequestInput::postStrVar('name');
$pwd = RequestInput::postRawStr('password');
JsonOut::ok(['list' => $rows]);
JsonOut::error('参数错误');
JsonOut::authError('未登录');
hope_abort('权限不足', './');
模板与 URL
include PageComposer::themePath('header'); // → head.php
include PageComposer::themePath('log_list'); // → archive.php
include PageComposer::themePath('pages/about'); // 独立页模板
include PageComposer::userPath('index'); // account/
SiteUrl::post($gid);
SiteUrl::category($sid);
SiteUrl::tag($tagname);
SiteUrl::plugin('tips', ['id' => 1]);
SiteUrl::userCenter(['api' => 1]);
URL 规则受后台「设置 → 链接」影响,见 伪静态与路由。
命名迁移速查
| 旧 |
现行 |
Option |
Settings |
View::getView |
PageComposer::themePath |
Url:: / Url::log |
SiteUrl:: / SiteUrl::post |
addAction / doAction |
hope_listen / hope_emit |
Database / Storage |
HopeDb / MetaStorage |
Cache / $CACHE |
SnapshotBank / $SNAP |
Input / Output |
RequestInput / JsonOut |
LoginAuth |
AuthSession |
*_Controller / *_Model |
*_Handler / *_Store |
完整对照与运行时垫片见 常见问题 · 旧版兼容。
开发规范
- PHP 遵循 PSR-1、PSR-12
- 文件开头:
defined('HOPE_ROOT') || exit('access denied!');
- 主题配置用
hope_option / _hope,始终带默认值
- 禁止在业务里
HopeDb::getInstance()->query() 拼接不可信输入
- 输出用户内容用
htmlspecialchars / hope_html_clean
开启开发者模式
方式一: 在 system/config.php 末尾:
const ENVIRONMENT = 'develop';
方式二: 后台开启「调试模式」。
上线前请改回 production 并关闭调试。错误日志多在 content/cache/error.log 或 content/logs/。
下一步
挂载点手册
Hope CMS 通过挂载点(Hook)在不改核心的前提下扩展功能。常量定义于 system/lib/hooks.php(HopeHooks),注册/触发 API 在 system/lib/common.php。
相关:开发准备工作 · 插件开发指南 · 伪静态与路由
API 一览
// 注册(推荐常量)
hope_listen(HopeHooks::INDEX_HEAD, 'myplugin_head_css');
hope_listen('adm_main_top', 'tips_render_admin_banner'); // 字符串亦可
// 触发
hope_emit(HopeHooks::INDEX_HEAD);
hope_emit(HopeHooks::SAVE_LOG, $gid, $logData);
| 函数 |
行为 |
典型场景 |
hope_listen($hook, $callback) |
注册回调 |
插件入口 |
hope_emit($hook, ...$args) |
执行该点全部回调 |
输出 CSS/JS、记日志 |
hope_emit_once($hook, $input, &$ret) |
仅第一个回调,可改 $ret |
接管上传、用户中心 API |
hope_emit_pipe($hook, $input, &$ret) |
链式执行,逐级变换 $ret |
正文过滤 |
hope_unlisten($hook, $callback) |
移除回调 |
调试 / 互斥 |
hope_has_listener($hook, $callback) |
是否已注册 |
条件注册 |
约定:
- 回调内输出用户内容用
htmlspecialchars
- 需要 JSON 中断时用
JsonOut::* / hope_abort(),避免半截 HTML
- 函数名加插件/主题前缀,避免冲突
启动与路由
| 常量 |
字符串 |
说明 |
HopeHooks::INIT |
init |
插件与主题 hooks.php 加载完成后 |
HopeHooks::ROUTE_DISPATCH |
route_dispatch |
路由分发前(model, method, params) |
HopeHooks::ROUTING_REGISTER |
routing_register |
路由表构建后扩展(hope_emit_pipe,可追加规则) |
HopeHooks::PAGE_NOT_FOUND |
page_not_found |
404 页 |
hope_listen(HopeHooks::ROUTING_REGISTER, 'myplugin_register_routes');
详见 伪静态与路由。
前台页面
| 常量 |
字符串 |
建议埋点位置 |
INDEX_HEAD |
index_head |
</head> 前 |
INDEX_BODY_START |
index_body_start |
<body> 后 |
INDEX_SIDEBAR |
index_sidebar |
侧边栏 widgets 之前 |
INDEX_FOOTER |
index_footer |
页脚脚本前 |
INDEX_BODY_END |
index_body_end |
</body> 前 |
主题模板负责 hope_emit(...),插件负责 hope_listen(...)。
文章与评论
| 常量 |
字符串 |
参数 / 说明 |
LOG_VIEW |
log_view |
文章页渲染前(logid, logData) |
ARTICLE_CONTENT_ECHO |
article_content_echo |
正文输出前过滤(hope_emit_pipe) |
LOG_RELATED |
log_related |
相关推荐 / 扩展区 |
LOG_DIRECT_LINK |
log_direct_link |
外链跳转前 |
SAVE_LOG |
save_log |
文章/页面保存后 |
DEL_LOG |
del_log |
文章/页面删除后 |
COMMENT_FORM |
comment_form |
评论表单区 |
COMMENT_POST |
comment_post |
评论提交前 |
COMMENT_SAVED |
comment_saved |
评论保存后 |
COMMENT_REPLY |
comment_reply |
后台回复评论后 |
POST_COMMENT |
post_comment |
前台评论发布成功 |
POST_NOTE |
post_note |
微语/笔记发布 |
hope_listen(HopeHooks::ARTICLE_CONTENT_ECHO, function ($content, &$ret) {
$ret = str_replace('foo', 'bar', $ret ?: $content);
});
用户与登录
| 常量 |
字符串 |
说明 |
USER_MENU |
user_menu |
用户中心侧栏扩展 |
USER_CENTER_API |
user_center_api |
个人中心 API(hope_emit_once,可接管 action) |
LOGIN_HEAD |
login_head |
登录页 head |
LOGIN_EXT |
login_ext |
登录表单扩展 |
LOGIN_SUCCESS |
login_success |
登录成功 |
SIGNUP_EXT |
signup_ext |
注册表单扩展 |
hope_listen(HopeHooks::USER_MENU, function () {
echo '<a href="' . htmlspecialchars(SiteUrl::plugin('myplugin')) . '">我的扩展</a>';
});
后台
| 常量 |
字符串 |
说明 |
ADM_HEAD |
adm_head |
后台 <head> |
ADM_FOOTER |
adm_footer |
后台页脚 |
ADM_MAIN_TOP |
adm_main_top |
后台首页顶部(如 tips 横幅) |
ADM_MAIN_BOTTOM |
adm_main_bottom |
后台首页底部 |
ADM_MENU |
adm_menu |
侧栏菜单项(靠前) |
ADM_MENU_EXT |
adm_menu_ext |
侧栏菜单末尾 |
ADM_WRITELOG_BAR |
adm_writelog_bar |
写文章工具栏 |
ADM_WRITELOG_TITLE |
adm_writelog_title |
写文章标题旁扩展 |
ADM_COMMENT_DISPLAY |
adm_comment_display |
评论列表扩展 |
ADM_LINK_DISPLAY |
adm_link_display |
链接列表扩展 |
ADM_USER_DISPLAY |
adm_user_display |
用户列表行($user) |
ADM_USER_FORM |
adm_user_form |
用户编辑表单 |
hope_listen(HopeHooks::ADM_MENU_EXT, function () {
echo '<li><a href="./?act=plugin_set&plugin=myplugin">我的插件</a></li>';
});
具体菜单 HTML 请对照当前后台模板。
用户管理事件
| 常量 |
字符串 |
参数 |
ADD_USER |
add_user |
uid, userData |
UPDATE_USER |
update_user |
uid, userData |
DEL_USER |
del_user |
uid |
FORBID_USER |
forbid_user |
uid |
UNFORBID_USER |
unforbid_user |
uid |
媒体与下载
| 常量 |
字符串 |
说明 |
UPLOAD_MEDIA |
upload_media |
附件上传(常配合 hope_emit_once 接管) |
DEL_MEDIA |
del_media |
附件删除 |
ATTACH_UPLOAD |
attach_upload |
编辑器附件上传 |
DOWNLOAD_RESOURCE |
download_resource |
资源下载 |
分类、设置与插件生命周期
| 常量 |
字符串 |
说明 |
SAVE_CATEGORY / DEL_CATEGORY |
save_category / del_category |
分类保存 / 删除后 |
SAVE_SETTING |
save_setting |
系统设置保存后 |
PLUGIN_ACTIVE |
plugin_active |
插件启用 |
PLUGIN_INACTIVE |
plugin_inactive |
插件停用 |
PLUGIN_DELETED |
plugin_deleted |
插件删除 |
LANG_LOADED |
lang_loaded |
语言包加载后 |
GET_GRAVATAR |
get_Gravatar |
Gravatar 地址(hope_emit_once) |
示例:最小可用
// myplugin.php
hope_listen(HopeHooks::ADM_HEAD, 'myplugin_admin_css');
hope_listen(HopeHooks::SAVE_LOG, 'myplugin_on_save');
function myplugin_admin_css() {
echo '<link rel="stylesheet" href="' . HOPE_PLUGINS_URL . 'myplugin/assets/admin.css">' . "\n";
}
function myplugin_on_save($gid, $data = null) {
// 文章保存后的业务逻辑
}
源码常量以 system/lib/hooks.php 为准;本页与代码不一致时以代码为准。
数据库与 SQL
Hope CMS 使用 MySQL / MariaDB。业务访问统一通过 HopeDb 与 HopeSql 完成。
- 生命周期 / MetaStorage:对照示例插件
tips
- 自建表:对照
oauth、video、music 的 *_upgrade_schema() / callback_init()
相关:插件开发指南 · 升级与更新
核心类与文件
| 类 |
路径 |
说明 |
HopeDb |
system/lib/database/hope_db.php |
数据库入口,链式查询与快捷方法 |
HopeQuery |
system/lib/database/hope_query.php |
链式查询构建器 |
HopeSql |
system/lib/database/hope_sql.php |
SQL 文件读取与批量执行 |
MetaStorage |
system/lib/database/meta_storage.php |
插件键值存储(hope_storage 表) |
HopeMysqli / HopePdo |
同目录 |
底层驱动 |
表前缀
const DB_PREFIX = 'hope_'; // system/config.php
约定:
HopeDb::table('article') 不要手动加前缀,框架会拼为 hope_article
- 原生 SQL 可拼接
DB_PREFIX,或在 HopeSql / HopeDb::executeFile 中使用 {db_prefix}
- 少数场景:
DB_PREFIX . 'myplugin_log'
链式查询(推荐)
$rows = HopeDb::table('myplugin_log')
->where(['status' => 1, 'uid' => $uid])
->whereLike('title', $keyword)
->whereIn('id', $ids)
->order('id DESC')
->limit(20, 0)
->findAll();
$row = HopeDb::table('myplugin_log')->where(['id' => $id])->find();
$total = HopeDb::table('myplugin_log')->where(['status' => 1])->count();
$list = HopeDb::table('myplugin_log', 'l')
->select(['l.id', 'l.title', 'u.nickname'])
->leftJoin('user', 'u', 'l.uid = u.uid')
->where(['l.status' => 1])
->order('l.id DESC')
->limit(10)
->findAll();
链式方法一览
| 方法 |
说明 |
select($fields) |
指定字段 |
where($condition) |
数组或字符串条件 |
whereRaw($sql) |
原生 WHERE 片段 |
whereIn / whereLike |
IN / 模糊 |
join / leftJoin |
表关联 |
order / limit / group |
排序、分页、分组 |
findAll / find |
多行 / 单行 |
insert / update / delete / count |
写与计数 |
快捷方法
HopeDb::select('article', ['hide' => 'n']);
HopeDb::getOne('user', ['uid' => 1]);
HopeDb::insert('myplugin_log', ['title' => '示例', 'status' => 1]);
HopeDb::update('myplugin_log', ['id' => 1], ['status' => 0]);
HopeDb::delete('myplugin_log', ['id' => 1]);
HopeDb::count('myplugin_log', ['status' => 1]);
原生 SQL
$rows = HopeDb::fetchAll(
'SELECT * FROM `' . DB_PREFIX . 'myplugin_log` WHERE uid = ' . (int) $uid
);
$row = HopeDb::fetchOne('SELECT COUNT(*) AS cnt FROM `' . DB_PREFIX . 'myplugin_log`');
HopeDb::execute('UPDATE `' . DB_PREFIX . 'myplugin_log` SET views = views + 1 WHERE id = ' . (int) $id);
$safe = HopeDb::escape($keyword);
优先链式 where / whereLike;原生 SQL 中数值 (int),字符串务必 HopeDb::escape()。
插件/主题建表(callback_init)
不再使用目录下的 install.sql 自动执行。启用时核心只调用 callback_init()。
function myplugin_upgrade_schema() {
$table = DB_PREFIX . 'myplugin_log';
if (HopeDb::fetchOne("SHOW TABLES LIKE '{$table}'")) {
return;
}
HopeDb::execute("CREATE TABLE IF NOT EXISTS `{$table}` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`title` varchar(255) NOT NULL DEFAULT '',
`uid` int unsigned NOT NULL DEFAULT 0,
`status` tinyint NOT NULL DEFAULT 1,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", true);
}
function callback_init() {
myplugin_upgrade_schema();
}
function callback_rm() {
MetaStorage::getInstance('myplugin')->deleteAllName('YES');
HopeSql::dropTables(['myplugin_log']);
}
何时执行
| 时机 |
调用 |
| 插件启用 |
callback_init() |
| 主题启用 |
主题 callback.php → callback_init() |
| 插件升级 |
callback_up()(通常再调同一 upgrade) |
| 手动 SQL 文件 |
HopeDb::executeFile / HopeSql::executeFile |
HopeSql 高级选项
HopeSql::executeFile(HOPE_ROOT . 'path/to/custom.sql', [
'replace_prefix' => true,
'ignore_error' => false,
'charset_setup' => false,
'version_gate' => false,
]);
HopeSql::dropTables(['table_a', 'table_b']):逻辑表名(不含前缀)批量 DROP。
字段升级(Schema Migration)
function myplugin_upgrade_schema_fields() {
static $done = false;
if ($done) return;
$done = true;
$table = DB_PREFIX . 'myplugin_log';
HopeDb::execute("CREATE TABLE IF NOT EXISTS `{$table}` (...)", true);
$existing = [];
foreach (HopeDb::fetchAll("SHOW COLUMNS FROM `{$table}`") as $col) {
$existing[$col['Field']] = true;
}
if (empty($existing['new_field'])) {
HopeDb::execute(
"ALTER TABLE `{$table}` ADD COLUMN `new_field` varchar(100) NOT NULL DEFAULT ''",
true
);
}
}
在 callback_init() / callback_up() 中调用同一函数即可。
$storage = MetaStorage::getInstance('tips');
$storage->setValue('config', [
'enabled' => 'y',
'per_page' => 20,
], 'array');
$config = $storage->getValue('config');
$storage->deleteAllName('YES');
适合开关、JSON 配置、计数;列表/关联数据请自建表。
系统核心表(只读参考)
不得修改以下核心表结构,仅可通过 Store / API 读写:
| 逻辑名 |
实际表名 |
说明 |
article |
hope_article |
文章/页面 |
user |
hope_user |
用户 |
comment |
hope_comment |
评论 |
sort / category |
视版本 |
分类 |
tag |
hope_tag |
标签 |
media |
hope_media |
附件 |
option |
hope_option |
系统配置 |
storage |
hope_storage |
插件键值存储 |
pay_order |
hope_pay_order |
支付订单 |
插件自建表命名建议:{DB_PREFIX}{插件名}_{用途},如 hope_oauth_bind。
开发建议
- 生命周期 → 先写好
callback_* 与 MetaStorage
- 新建表 →
callback_init / *_upgrade_schema()
- 加字段 → 同一升级函数内
SHOW COLUMNS + ALTER
- 日常查询 → 优先
HopeDb::table() 链式
- 复杂 SQL →
fetchAll / fetchOne / execute,注意转义
- 卸载清理 →
callback_rm() 必须清 MetaStorage;有表则明确是否 DROP
主题开发指南
主题位于 content/theme/{主题目录}/。启用后前台页面由该目录下的 PHP 模板渲染。
官方示例主题:content/theme/default/。学习列表页、侧边栏、用户中心、CSF 设置时优先对照此主题。
相关文档:开发准备工作 · 挂载点手册 · 侧边栏开发说明 · 伪静态与路由 · 数据库与 SQL
站内「主题生成器」页可拼装主题 PHP 片段(输出适配现行 Hope CMS API)。
1. 从零创建主题
- 复制
content/theme/default/ 为 content/theme/你的主题/
- 修改
head.php 顶部 Theme Name / Version / Description
- 修改
settings.php 的 $prefix(如 yourtheme_options)与标题文案
- 将
functions.php 中函数前缀(如 nova_*)改为自己的命名空间,避免冲突
- 后台 外观 → 主题 启用;如有
callback.php,启用时会执行 callback_init()
- 建议执行一次 设置 → 更新缓存
- 到 外观 → 侧边栏 检查组件是否仍可用
不要直接改正在线上使用的主题;复制一份再改,便于回滚。
2. 目录结构
官方 default 采用下列命名(推荐新主题照此创建):
content/theme/default/
├── head.php # 必需:主题元信息 + HTML 头部
├── foot.php # 必需:页脚与闭合标签
├── archive.php # 必需:首页 / 分类 / 标签 / 搜索 / 归档列表
├── single.php # 必需:文章详情
├── 404.php # 推荐:404 页
├── functions.php # 推荐:主题函数库(模板中 require)
├── settings.php # 可选:CSF 主题设置
├── hooks.php # 可选:主题级钩子(每请求自动 include)
├── callback.php # 可选:启用 / 删除 / 升级回调
├── preview.png # 推荐:后台主题列表预览图
├── widgets/ # 可选:侧边栏
│ ├── sidebar.php
│ ├── config.php # 组件注册表(注册 key 仍可用 side_*)
│ └── widget-*.php # 如 widget-blogger.php
├── pages/ # 可选:独立页面模板
│ └── page.php
├── account/ # 可选:登录 / 注册 / 用户中心
│ ├── index.php
│ ├── login.php
│ ├── register.php
│ ├── auth.php
│ └── profile.php
├── partials/ # 可选:可复用片段
└── assets/ # 静态资源
├── css/
├── img/
└── js/
最小可运行主题
至少需要:head.php、foot.php、archive.php、single.php。其余按需增加。
3. 主题元信息
写在 head.php 文件最顶部的注释块,后台主题列表会解析:
<?php
/*
Theme Name: 默认主题
Theme Type: cms
Theme Url: http://www.hopecms.cn
Author: Hope CMS
Author Url: http://www.hopecms.cn
Version: 1.0.0
Description: Hope CMS 默认主题:大标题首页、双栏列表、标签云侧栏与个人中心。
*/
defined('HOPE_ROOT') || exit('access denied!');
require_once PageComposer::themePath('module'); // → functions.php
| 字段 |
说明 |
| Theme Name |
后台显示名称(必需) |
| Version |
版本号 |
| Description |
简介 |
| Theme Type |
可选分类关键词(见下表);可写多个,后台按匹配显示中文标签 |
| Author / Theme Url |
作者与主题主页 |
Theme Type 与后台展示对应关系(Theme_Store):
| 写入值(英文关键词) |
后台显示 |
cms |
博客 |
music |
音乐 |
video |
视频 |
forum |
论坛 |
示例:Theme Type: cms → 显示「博客」;Theme Type: cms video → 显示「博客.视频」。
4. 核心模板与变量
控制器先 include PageComposer::themePath('header'),再 include 列表或详情模板;模板内再 include footer(逻辑名;物理文件可为 head.php / foot.php)。
4.1 列表页 archive.php(逻辑名 log_list)
用于首页、分类、标签、搜索、日期归档、作者页等。
| 变量 |
说明 |
$logs |
当前页文章数组 |
$lognum |
符合条件的文章总数 |
$page / $index_lognum / $pageurl |
分页参数 |
$sortName / $sort |
分类名 / 分类信息(分类页) |
$tag |
标签名(标签页) |
$keyword |
搜索关键词(搜索页) |
$record |
归档年月(归档页) |
$author_name |
作者展示名(作者页) |
$page_html = hope_pagination($lognum, $index_lognum, $page, $pageurl);
foreach ($logs as $value) {
// $value['gid'] $value['log_title'] $value['log_cover'] ...
echo '<a href="' . SiteUrl::post($value['gid']) . '">'
. htmlspecialchars($value['log_title']) . '</a>';
}
列表变体(可选):archive_card.php / archive_grid.php / archive_seamless.php,可由主题设置切换;薄封装内通常 include PageComposer::themePath('archive')。
4.2 详情页 single.php(逻辑名 echo_log)
| 变量 |
说明 |
$logid / $gid |
文章 ID |
$log_title / $log_content |
标题 / 正文 HTML |
$log_cover |
封面图 URL |
$date / $views / $comnum |
时间戳 / 阅读 / 评论数 |
$author / $sortid / $tags |
作者 UID / 分类 ID / 标签 ID 串 |
$neighborLog |
上一篇 / 下一篇 |
$password |
访问密码(有则需校验) |
<?php include PageComposer::themePath('sidebar'); ?>
<?php include PageComposer::themePath('footer'); ?>
| 变量 |
说明 |
$site_title |
当前页 <title> |
$site_key / $site_description |
SEO keywords / description |
$sitename |
站点名(系统设置) |
头部 / 页脚应输出挂载点:
<?php hope_emit('index_head'); ?>
<?php hope_emit('index_footer'); ?>
站点标题请读系统设置,例如:
htmlspecialchars((string) Settings::get('sitename'));
// 或主题助手:hope_site_name() / hope_site_info()
5. 自定义页面
后台创建「页面」时可选择模板,文件放在 pages/:
<?php
/*@name 关于我们*/
defined('HOPE_ROOT') || exit('access denied!');
?>
<main>
<h1>关于我们</h1>
<div><?= $log_content ?></div>
</main>
<?php include PageComposer::themePath('footer'); ?>
@name 后的文字会出现在后台模板下拉里
- 页面同样会先加载
head.php(逻辑名 header),模板内记得闭合 footer
- 复杂站点(如本主题
hopecms)可有多个:page_docs.php、page_download.php、page_generator.php(主题生成器)等
6. functions.php
建议所有主题辅助函数集中在此,并在 head.php 中:
require_once PageComposer::themePath('module'); // 逻辑名 → functions.php
function your_asset($path) {
$path = ltrim((string) $path, '/');
if ($path !== '' && strpos($path, 'assets/') !== 0) {
$path = 'assets/' . $path;
}
return THEME_URL . $path;
}
function your_brand() {
$name = trim((string) Settings::get('sitename'));
return htmlspecialchars($name !== '' ? $name : 'Hope CMS');
}
| 常量 |
说明 |
THEME_PATH |
当前主题物理路径 |
THEME_URL |
当前主题 URL |
SITE_URL |
站点根 URL(含末尾 /) |
生成内容链接用核心类,不要手拼规则:
SiteUrl::post($gid); // 文章
SiteUrl::category($sid); // 分类
SiteUrl::tag($tagname); // 标签
SiteUrl::author($uid); // 作者
SiteUrl::userCenter(); // 个人中心
7. settings.php(主题设置)
主题目录内有 settings.php 时,后台出现主题设置页(Codestar / CSF)。
约定
| 项 |
说明 |
$prefix |
唯一,推荐 {主题目录}_options;设定后勿改 |
| 读取 |
hope_option('字段id', '默认值') 或 _hope() |
| 无文件 |
无主题设置页,主题仍可正常启用 |
| 站点信息 |
标题 / 副标题 / SEO / 版权走后台「设置」;主题用 Settings::get('sitename') 读取 |
<?php
if (!defined('HOPE_ROOT')) exit;
$prefix = 'yourtheme_options';
CSF::createOptions($prefix, [
'plugin_title' => '某某主题设置',
'footer_text' => 'Hope CMS',
'theme' => 'light', // light | dark | auto
]);
CSF::createSection($prefix, [
'title' => '基本设置',
'icon' => 'fa fa-cog',
'fields' => [
[
'type' => 'notice',
'style' => 'info',
'content' => '站点标题、副标题、SEO 描述与页脚版权请在后台「设置 → 站点信息 / SEO 设置」中维护。',
],
[
'id' => 'primary_color',
'type' => 'color',
'title' => '主题色',
'default' => '#3b82f6',
],
[
'id' => 'hero_enable',
'type' => 'switcher',
'title' => '启用首页 Hero',
'default' => true,
],
],
]);
options完整的.php 覆盖:文本、选择、开关、上传、颜色、调色板、repeater/group、accordion/tabbed、code_editor、依赖 dependency、backup 等。
WordPress Codestar 可迁移:API 用 CSF::;读取用 hope_option(),不要用 get_option。
8. hooks.php(主题钩子)
每个前台请求在加载已启用插件之后,会自动 include 当前主题的 hooks.php(若存在),再执行 hope_emit('init')。
适合:注册主题专属钩子、挂文章自定义字段、改写用户中心菜单等。
<?php
defined('HOPE_ROOT') || exit('access denied!');
hope_listen('index_head', 'yourtheme_extra_css');
hope_listen('user_menu', 'yourtheme_user_menu_item');
9. callback.php(主题生命周期)
| 函数 |
时机 |
callback_init() |
主题启用时 |
callback_rm() |
主题删除前 |
callback_up() |
主题升级后(若实现) |
可在启用时建表、写默认配置;删除时清理 MetaStorage / 自建表。建表写法见 数据库与 SQL。
<?php
defined('HOPE_ROOT') || exit('access denied!');
function callback_init() {
// 同步默认配置、建扩展表
}
function callback_rm() {
// MetaStorage::getInstance('yourtheme')->deleteAllName('YES');
}
10. 侧边栏与用户中心
- 侧边栏:
widgets/ + config.php,详见 侧边栏开发说明
- 用户中心:优先使用主题
account/;若主题未提供,系统可能回退到其它主题的 user/
- 登录 / 注册页同理,建议主题内自备完整
account/ 目录
include PageComposer::userPath('index');
11. 挂载点(主题侧)
主题模板负责 埋点,插件负责 注册回调。
| 挂载点 |
建议位置 |
index_head |
</head> 前 |
index_body_start |
<body> 后 |
index_footer / index_body_end |
页脚脚本区 |
index_sidebar |
侧边栏容器内 |
log_related |
文章相关推荐区 |
完整列表见 挂载点手册。
12. 检查清单与注意事项
- 不硬编码域名,用
SITE_URL、THEME_URL、SiteUrl::*
- 输出用户内容用
htmlspecialchars
- 勿修改
system/;业务扩展用主题 hooks.php 或独立插件
$prefix 与函数名前缀全局唯一
hope_option / _hope 始终带默认值
SITE_URL 已有尾斜杠,拼接时避免双斜杠
- 静态资源建议放在
assets/
- 启用新主题后更新缓存;换主题后检查侧边栏组件是否仍注册
- 站点标题 / SEO 用系统设置,不在主题 CSF 重复配置
插件开发指南
插件是在不修改 system/ 核心的前提下扩展 Hope CMS 的主要方式:通过挂载点插入逻辑、可选建表、提供后台设置页与前台页面。
官方示例插件: content/plugin/tips/(小贴士)。无自建表、结构完整,适合作为脚手架。
有表 / 存储的对照:content/plugin/oauth/(callback_init 建表 + MetaStorage 配置)。
相关文档:开发准备工作 · 挂载点手册 · 数据库与 SQL · 升级与更新 · 伪静态与路由 · API 开发文档 · 常见问题
1. 从 tips 起步
- 复制
content/plugin/tips/ → content/plugin/你的插件名/
- 目录名与入口文件名一致:
你的插件名/你的插件名.php
- 重命名
tips_*.php,并全局替换函数前缀(如 tips_ → myplugin_)
- 修改入口文件头信息中的 Plugin Name / Description / Version
- 后台 插件 → 插件管理 启用
- 确认钩子生效;需要持久化时再补
MetaStorage / 建表
启用时核心流程:写入 active_plugins → 加载 {插件}_callback.php → 调用 callback_init()(不会自动执行 install.sql)。
每请求加载:对已启用插件 include_once content/plugin/{名}/{名}.php,再加载当前主题 hooks.php,最后 hope_emit('init')。
2. 目录结构
content/plugin/tips/
├── tips.php # 必需:入口 + 头信息 + 注册钩子
├── tips_callback.php # 强烈推荐:启用 / 更新 / 删除
├── tips_setting.php # 可选:后台设置页(有则显示「设置」)
├── tips_lib.php # 推荐:业务函数
├── tips_show.php # 可选:前台独立页(SiteUrl::plugin)
├── preview.png # 可选:插件列表预览图
└── assets/
└── tips.css
| 文件 |
必需 |
说明 |
{名}.php |
是 |
入口;启用期间每个请求都会加载 |
{名}_callback.php |
强烈建议 |
callback_init / callback_up / callback_rm |
{名}_setting.php |
否 |
定义 plugin_setting_view() |
{名}_lib.php |
建议 |
函数库 |
{名}_show.php |
否 |
前台展示页 |
{名}_rewrite.php 等 |
否 |
按需拆分(如伪静态规则) |
命名规则:目录名、入口文件名、钩子函数前缀保持一致。
3. 入口文件与头信息
<?php
/*
Plugin Name: 小贴士
Version: 1.0.0
Plugin URL: http://www.hopecms.cn
Description: 插件启用后,在后台首页随机展示一句内置使用提示。
Author: Hope CMS
Author URL: http://www.hopecms.cn
*/
!defined('HOPE_ROOT') && exit('error');
require_once HOPE_ROOT . 'content/plugin/tips/tips_lib.php';
hope_listen('adm_main_top', 'tips_render_admin_banner');
hope_listen('adm_head', 'tips_enqueue_admin_css');
| 头字段 |
说明 |
| Plugin Name |
后台显示名(必需) |
| Version |
版本号 |
| Description |
简介 |
| Plugin URL / Author / Author URL |
可选元数据 |
active_plugins 中存储的是相对路径:tips/tips.php。
4. 生命周期回调
文件:content/plugin/{名}/{名}_callback.php
| 函数 |
时机 |
典型工作 |
callback_init() |
启用时 |
建表、写默认 MetaStorage、注册一次性数据 |
callback_up() |
更新插件后 |
通常再调 callback_init() 或 *_upgrade_schema() |
callback_rm() |
删除前 |
删 MetaStorage、HopeSql::dropTables([...]) |
tips(无表)
<?php
defined('HOPE_ROOT') || exit('access denied!');
function callback_init() {
}
function callback_up() {
callback_init();
}
function callback_rm() {
MetaStorage::getInstance('tips')->deleteAllName('YES');
}
有表时(对照 oauth)
function callback_init() {
require_once HOPE_ROOT . 'content/plugin/oauth/oauth_lib.php';
oauth_upgrade_schema(); // 内含 CREATE TABLE IF NOT EXISTS
$storage = MetaStorage::getInstance('oauth');
if (!$storage->getValue('config')) {
$storage->setValue('config', oauth_default_config(), 'array');
}
}
function callback_rm() {
MetaStorage::getInstance('oauth')->deleteAllName('YES');
HopeSql::dropTables(['oauth_bind']); // 不带表前缀
}
要点:
- 建表在 PHP 里执行,不要依赖自动跑
install.sql
HopeDb::table('xxx') 不带前缀;原生 SQL / dropTables 注意 DB_PREFIX
- 卸载是否删表由你决定:商业数据可选择只清 MetaStorage、保留业务表
详见 数据库与 SQL、升级与更新。
5. 挂载点(Hook)
hope_listen('adm_main_top', 'tips_render_admin_banner');
hope_listen(HopeHooks::ADM_HEAD, 'tips_enqueue_admin_css'); // 推荐常量
| API |
行为 |
hope_emit($hook, ...) |
执行该点全部回调 |
hope_emit_once($hook, $input, &$ret) |
只跑第一个,可改 $ret |
hope_emit_pipe($hook, $input, &$ret) |
链式变换 $ret |
hope_unlisten / hope_has_listener |
移除 / 判断 |
常用挂载点
| 常量 / 字符串 |
用途 |
init |
插件与主题 hooks 加载完后 |
index_head / index_footer |
前台头尾 |
index_body_start / index_body_end |
body 始末 |
adm_head / adm_footer |
后台头尾 |
adm_menu / adm_menu_ext |
后台侧栏菜单 |
adm_main_top |
后台首页顶部(tips 横幅) |
adm_writelog_bar |
写文章工具栏 |
user_menu |
用户中心侧栏 |
user_center_api |
用户中心 API 扩展 |
save_log / del_log |
文章保存 / 删除后 |
log_view / log_related |
文章渲染前 / 相关推荐 |
comment_saved / post_comment |
评论相关 |
upload_media |
媒体上传(常配合 hope_emit_once) |
plugin_active / plugin_inactive |
启停插件时 |
routing_register |
注册前台路由 |
完整参数与示例见 挂载点手册。
约定: 钩子回调里输出 HTML 时对用户数据做 htmlspecialchars;需要中断请求时用 JsonOut::* / hope_abort()。
6. 后台设置页
存在 {名}_setting.php 且插件已启用时,插件列表显示「设置」。
访问:{后台入口}?act=plugin_set&plugin=tips
(默认入口为 admin.php,生产环境应重命名。)
必须定义:
<?php
defined('HOPE_ROOT') || exit('access denied!');
function plugin_setting_view() {
// 输出后台 HTML(可沿用 content/admin 的 Bootstrap / card 样式)
}
保存配置推荐两种方式:
A. MetaStorage(键值,适合开关与小配置)
$storage = MetaStorage::getInstance('myplugin');
$storage->setValue('config', ['enable' => 1], 'array');
$config = $storage->getValue('config');
B. 自建表
用 HopeDb::table(...)->insert/update;设置页里处理 POST 时用 RequestInput::postStrVar 等过滤。
设置页由核心保证管理员登录;若另写 AJAX 接口,须自行校验:
if (!AuthSession::isLogin() || ROLE !== ROLE_ADMIN) {
JsonOut::authError('权限不足');
}
7. 前台页面 {名}_show.php
放置该文件且插件已启用时,可通过插件路由访问:
$url = SiteUrl::plugin('tips');
$url = SiteUrl::plugin('tips', ['id' => 1]);
- 未启用或文件不存在 → 404
- 页面可自绘完整 HTML,也可 include 当前主题头尾保持站点风格
include PageComposer::themePath('header');
// ... 插件内容 ...
include PageComposer::themePath('footer');
静态资源:
function tips_asset_url($path) {
return HOPE_PLUGINS_URL . 'tips/assets/' . ltrim($path, '/');
}
| 常量 |
说明 |
HOPE_PLUGINS_PATH |
content/plugin/ 物理路径 |
HOPE_PLUGINS_URL |
content/plugin/ URL 前缀 |
8. 数据库与配置
| 场景 |
推荐 |
| 开关、JSON 配置、计数 |
MetaStorage::getInstance('插件名') |
| 列表、关联、订单等 |
自建表 + HopeDb::table |
| 系统级选项 |
Settings::get / Settings::updateOption(慎用,避免污染核心键) |
$rows = HopeDb::table('myplugin_log')
->where(['uid' => $uid])
->order('id DESC')
->limit(20)
->findAll();
禁止在业务里直接拼接不可信输入执行 SQL。详见 数据库与 SQL。
9. 安全规范
- 每个 PHP 文件检查
HOPE_ROOT
- 读写请求用
RequestInput::getIntVar / postStrVar / postRawStr
- 输出 HTML 用
htmlspecialchars;JSON 用 JsonOut::ok / JsonOut::error
- CSRF:后台表单遵循现有 admin 习惯;前台写操作校验登录态与 token
- 不修改核心表结构语义;不覆盖
system/、content/admin 核心文件
- SQL 表名、字段名白名单化,勿把用户输入拼进标识符
10. 调试
system/config.php 增加 const ENVIRONMENT = 'develop';,或后台开启调试模式
- 错误日志:
content/logs/ 或 content/cache/error.log
- 改钩子后:禁用再启用插件,确保
callback_init 重跑
- 确认
active_plugins 中路径为 目录/入口.php
- 前台
_show.php 404:检查是否启用、文件名是否 {名}_show.php、链接是否 SiteUrl::plugin
11. 与主题的分工
| 能力 |
放插件 |
放主题 |
| 跨主题可复用功能 |
✓ |
|
| 仅当前皮肤的样式 / 布局 |
|
✓ |
| 商业支付、OAuth、统计 |
✓ |
主题只负责展示 |
| CSF 外观选项 |
|
✓ settings.php |
| 文章保存后业务逻辑 |
✓ save_log |
主题 hooks 仅皮肤相关 |
Shop 等主题依赖的商业能力应做成普通插件,可启用 / 禁用 / 删除,而不是改核心。
12. 发布检查清单
- [ ] 头信息完整,Version 可递增
- [ ]
callback_rm 清理 MetaStorage;有表则明确是否 dropTables
- [ ]
callback_up / *_upgrade_schema 可重复执行(IF NOT EXISTS / 判列)
- [ ] 设置页、前台页在未启用时不可访问
- [ ] 函数名、MetaStorage 名、表名带插件前缀,无全局污染
- [ ] 附简短说明(README 或设置页文案)
- [ ] 在 PHP 7.4+ / 8.x 各测一次启停与卸载
13. 最小插件骨架
<?php
/*
Plugin Name: 演示插件
Version: 1.0.0
Description: 最小可运行示例
Author: You
*/
!defined('HOPE_ROOT') && exit('error');
hope_listen('adm_head', function () {
echo "<!-- myplugin loaded -->\n";
});
仅入口也可运行;正式发布请补全 _callback.php 与卸载清理。
伪静态与 URL 路由
Hope CMS 通过 链接模式(linkmode) 与 路由表 控制前台 URL 形态。后台在 设置 → 链接 中配置;路由表由 Settings::getEnhancedRoutingTable() 生成,由 Hope\Http\FrontRouter 匹配并分发到对应 *_Handler。
相关:挂载点手册 · API 开发文档 · 插件开发指南
链接模式
linkmode |
名称 |
URL 形态 |
说明 |
0 |
动态 |
?article=1、?category=2&page=3 |
无需服务器重写,兼容性最好 |
1 |
伪静态 |
/article/1.html、/user |
需将路径重写到 index.php |
2 |
index.php 式 |
/index.php/article/1.html |
依赖 PATH_INFO,部分主机更稳定 |
$linkmode = (string) Settings::get('linkmode');
$isRewrite = ($linkmode === '1' || $linkmode === '2');
保存链接设置后会刷新路由缓存。
后台 设置 → 更新缓存(全量 $SNAP->refresh())也会一并调用 Settings::resetRoutingTableCache(),清空进程内路由表缓存。单独刷新 options 缓存时同样会重置路由表。
首页分页规则 /page/{%page%}/ 与独立页 /page/{%alias%}.html 共用 page 前缀。路由引擎会保留尾斜杠,并将首页页码限制为数字,避免 /page/docs.html 被误判为分页。
后台 URL 规则
在 设置 → 链接 → 伪静态管理 中可配置(hope_option 键名):
| 配置项 |
动态模式默认 |
伪静态模式默认 |
用途 |
rule_index |
?page={%page%} |
/page/{%page%}/ |
首页列表 |
rule_article |
?article={%id%} |
/article/{%id%}.html |
文章详情 |
rule_page |
?id={%id%} |
/page/{%alias%}.html |
独立页面 |
rule_category |
?category={%id%}&page={%page%} |
/category/{%alias%}/{%page%}/ |
分类列表 |
rule_tag |
?tags={%tag%}&page={%page%} |
/tags-{%tag%}_{%page%}.html |
标签列表 |
rule_record |
?record={%record%}&page={%page%} |
/date/{%record%}/{%page%}/ |
日期归档 |
生成链接时由 SiteUrl 替换占位符。
常用占位符
| 占位符 |
说明 |
{%host%} |
站点 URL(SITE_URL) |
{%id%} |
数字 ID(含义由所在规则决定) |
{%alias%} |
按规则隔离:文章/分类/页面各自别名 |
{%category%} / {%category_alias%} |
所属分类标识(文章规则用) |
{%category_name%} |
分类显示名 |
{%page%} |
分页页码 |
{%tag%} |
标签名 |
{%record%} |
日期归档(YYYYMM / YYYYMMDD) |
{%year%} / {%month%} / {%day%} |
文章发布日期 |
{%parent%} |
父分类别名 |
变量隔离: 文章路径里的分类请写 {%category_alias%};分类列表自身写 {%alias%}。
分页占位符 {%page%} 在生成非分页链接时会被自动剔除。推荐连接写法:/{%page%}/、_{%page%}、-{%page%}、?page={%page%}。
自定义首页(home_page_id > 0)时,文章列表分页由 SiteUrl::postPage() 生成,路径可能带 posts/ 前缀。
分类勿写成 {%alias%}/{%page%}.html 同时文章用 {%category_alias%}/{%alias%}.html(同形会抢匹配)。推荐:文章 article/{%id%}.html、分类 category/{%alias%}/{%page%}/、独立页 page/{%alias%}.html。
内置活动路由
| 路径 / 参数 |
Handler |
说明 |
?author=1 |
Author |
作者页 |
?keyword=关键词 |
Search |
搜索 |
/user 或 ?user |
User |
个人中心 |
/login 或 ?login |
User::login |
登录 |
/register 或 ?register |
User::register |
注册 |
/auth_api 或 ?auth_api |
User::authApi |
认证 API |
?rest-api=方法名 |
Api / Pay |
REST API |
/plugin/插件名 或 ?plugin=插件名 |
Plugin |
插件前台页 |
?resource_alias=别名 |
Download |
附件下载 |
POST ?action=addcom |
Comment |
提交评论 |
伪静态示例:/user、/login、/register、/plugin/video
动态示例:?user、?login、?plugin=video
请求匹配流程
浏览器请求
→ Web 服务器重写到 index.php(伪静态时)
→ FrontRouter 解析路径
→ Settings 路由表按优先级匹配
→ 校验 must_get / 方法
→ 写入 $_GET
→ *_Handler 执行
要点:
- 伪静态模式跳过纯 query 型内容路由;动态模式跳过纯 path 型 rewrite 路由
- 活动路由排在默认首页路由之前,避免
?category=1 被首页抢走
- 插件可通过
HopeHooks::ROUTING_REGISTER 向路由表头部追加规则
Web 服务器配置
Apache(站点根目录 .htaccess)
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [L]
</IfModule>
子目录安装(如 /hope/)将 RewriteBase 改为 /hope/。
Nginx
location / {
try_files $uri $uri/ /index.php?$query_string;
}
index.php 式(linkmode=2) 若无效可改用:
location / {
if (!-e $request_filename) {
rewrite ^/(.*)$ /index.php/$1 last;
}
}
IIS
需安装 URL Rewrite,将请求重写到 index.php。系统兼容 HTTP_X_REWRITE_URL。
改服务器配置后,先确认后台 linkmode 与规则已保存,再逐项测试文章、分类、用户中心。
生成链接(开发)
主题与插件应使用 SiteUrl,不要手写路径:
SiteUrl::post($gid);
SiteUrl::category($sid);
SiteUrl::tag($tagname);
SiteUrl::postPage();
SiteUrl::userCenter(['api' => 1]);
SiteUrl::plugin('video', ['vid' => 1]);
SiteUrl::login();
SiteUrl::register();
SiteUrl::plugin() 在伪静态下生成 /plugin/video?vid=1,在动态下生成 ?plugin=video&vid=1。
插件扩展伪静态
站点 已开启 linkmode 1 或 2 时,可注册独立 path 规则:
- 新建
{插件名}_rewrite.php,实现注册函数
- 入口中
hope_listen(HopeHooks::ROUTING_REGISTER, 'xxx_register_rewrite_routes')
- 可选:提供
processor 回调,将路径参数写入 $_GET
hope_listen(HopeHooks::ROUTING_REGISTER, 'myplugin_register_routes');
function myplugin_register_routes($table, &$routes) {
$linkmode = (string) Settings::get('linkmode');
if ($linkmode !== '1' && $linkmode !== '2') {
return;
}
$routes = array_merge([
[
'type' => 'rewrite',
'model' => 'Plugin_Handler', // 以当前核心约定为准
'method' => 'loadPluginShow',
'pattern' => '/myplugin/{%id&type=num%}',
'processor' => function ($params, $route) {
$_GET['plugin'] = 'myplugin';
$params['plugin'] = 'myplugin';
return $params;
},
],
], $routes);
}
路由项字段
| 字段 |
说明 |
type |
rewrite / query / active |
model / method |
Handler 与方法 |
pattern |
支持 {%param%}、{%param&type=num%} |
must_get |
必须存在的 $_GET 键 |
processor |
匹配成功后的参数处理 |
request_method |
限制 GET / POST |
Pattern 类型修饰:{%id&type=num%} 仅数字;{%slug&type=alnum%} 字母数字。
对照现成实现:content/plugin/video/video_rewrite.php(若存在)。
常见问题
开启伪静态后全部 404
- 检查是否重写到
index.php
- 子目录确认
RewriteBase / SITE_URL
- 确认
linkmode 为 1 或 2 且规则已保存
首页正常,文章/分类 404
- 检查
rule_article、rule_category 是否与服务器兼容
- 勿遗漏必要占位符;保存后「更新缓存」
插件伪静态不生效
- 站点
linkmode 必须为 1 或 2
- 确认
routing_register 已注册且插件已启用
- 更具体的
pattern 应用 array_merge($newRoutes, $routes) 插到表头
动态模式下用户中心 API
?user&api=1&action=profile
- 认证专用:
/auth_api 或 ?auth_api
- 使用
SiteUrl::userCenter()、SiteUrl::authApi(),勿硬编码
相关文件
| 文件 |
职责 |
system/Hope/Config/Settings.php |
路由表、linkmode |
system/Hope/Http/FrontRouter.php |
路径解析与匹配 |
system/lib/http/site_url.php |
按规则生成链接 |
system/lib/hooks.php |
ROUTING_REGISTER |
content/admin/setting.php |
后台链接配置界面 |
API 开发文档
Hope CMS 提供 REST 风格接口,通过 URL 参数 rest-api 指定方法名。响应均为 JSON。
相关:伪静态与路由 · 挂载点手册 · 插件开发指南
基础地址
http://www.hopecms.cn/?rest-api={方法名}
示例:
GET http://www.hopecms.cn/?rest-api=article_list&page=1&count=10
开关
除支付相关接口外,其余 API 需在后台开启 OpenAPI(Settings::get('is_openapi') !== 'n'),否则返回 api is closed。
支付接口(pay_notify、pay_create、pay_cashier、pay_status)不受此限制。
鉴权方式
需要鉴权的接口(如发文、上传)支持两种方式:
1. API Key 签名(服务端 / 第三方)
后台「设置 → API」获取 apikey,请求携带:
| 参数 |
说明 |
req_time |
当前 Unix 时间戳(与服务器时差 ≤ 300 秒) |
req_nonce |
必填,16–64 位十六进制随机串,防重放 |
req_sign |
md5(req_time + req_nonce + apikey) |
$req_time = time();
$req_nonce = bin2hex(random_bytes(16));
$apikey = '你的apikey';
$req_sign = md5($req_time . $req_nonce . $apikey);
POST http://www.hopecms.cn/?rest-api=article_post&req_time=...&req_nonce=...&req_sign=...
缺少参数、签名错误或 nonce 重放时返回相应错误信息。
2. 登录 Cookie(浏览器端)
已登录用户携带站点认证 Cookie 时,可免 API Key,且 author_uid 可自动取当前用户。
响应格式
成功:
{ "code": 200, "msg": "ok", "data": { ... } }
失败:
{ "code": 0, "msg": "错误说明" }
认证失败:code 多为 401(以 JsonOut::authError 实际返回为准)。
文章接口
article_list — 文章列表
GET ?rest-api=article_list
| 参数 |
类型 |
说明 |
page |
int |
页码,默认 1 |
count |
int |
每页条数 |
category_id |
int |
分类 ID |
keyword |
string |
标题关键词 |
tag |
string |
标签名 |
order |
string |
views / comnum,默认按置顶与时间 |
返回 data.articles(含 id、title、cover、url、date、author_name、tags 等)。
article_detail — 文章详情
GET ?rest-api=article_detail&id=1
密码保护文章返回错误。成功返回 data.article。
article_post — 发布文章
POST ?rest-api=article_post
需鉴权。主要字段:title、content(必填),以及 excerpt、category_id、tags、cover、draft、alias、top、sortop、allow_remark、password、template 等。
article_update — 更新文章
POST ?rest-api=article_update
需鉴权。需传 id 及要更新的字段。
分类与微语
| 接口 |
方法 |
说明 |
category_list |
GET |
分类列表 |
note_list |
GET |
微语列表 |
note_post |
POST |
发布微语(需鉴权) |
评论与用户
| 接口 |
方法 |
说明 |
comment_list |
GET |
文章评论,id 为文章 ID |
userinfo |
GET |
当前登录用户信息(需 Cookie) |
个人中心 API
前台个人中心通过 ?user&api=1(或伪静态 /user?api=1)调用,需登录 Cookie。POST 须携带页面输出的 token。
GET http://www.hopecms.cn/?user&api=1&action=profile
POST http://www.hopecms.cn/?user&api=1
Body: token=...&action=profile&nickname=...
| action |
方法 |
说明 |
profile |
GET / POST |
读取或更新个人资料 |
avatar_upload |
POST |
上传头像 |
avatar_qq |
POST |
使用 QQ 头像 |
recharge |
POST |
创建充值订单 |
recharge_records |
GET |
充值记录 |
invite_info |
GET |
邀请码与奖励统计 |
forum_posts / forum_get / forum_save / forum_delete |
— |
论坛相关(主题提供时) |
forum_categories |
GET |
可选论坛分类 |
my_comments |
GET |
我的评论 |
comment_reply |
POST |
回复评论 |
my_media / media_upload / media_delete |
— |
媒体库 |
业务实现位于 system/app/service/(如 UserHub / 用户中心模块)。主题可在 account/ 提供模板并对接前端 JS。
插件可通过 HopeHooks::USER_CENTER_API(hope_emit_once)扩展自定义 action。
媒体上传
POST ?rest-api=upload
需 API Key 鉴权。multipart/form-data 字段:file、可选 sid、author_uid。
成功返回 media_id、url、file_info。
支付接口
由 Pay_Handler 处理,不依赖 OpenAPI 开关:
| 接口 |
说明 |
pay_create |
创建支付订单 |
pay_cashier |
收银台页面数据 |
pay_status |
查询订单状态 |
pay_notify |
支付平台异步回调 |
网关密钥、回调 URL 在后台 支付设置 中配置。参数以 system/app/handler/pay_handler.php 及支付插件为准。
若后台开启 API 限流,超限请降低频率或调整限额。
调用示例(PHP)
$base = 'http://www.hopecms.cn/';
$req_time = time();
$req_nonce = bin2hex(random_bytes(16));
$apikey = 'your_apikey';
$sign = md5($req_time . $req_nonce . $apikey);
$url = $base . '?rest-api=article_list&page=1&count=5'
. '&req_time=' . $req_time
. '&req_nonce=' . $req_nonce
. '&req_sign=' . $sign;
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$body = curl_exec($ch);
curl_close($ch);
$data = json_decode($body, true);
扩展 API
优先通过插件扩展,避免直接改核心 Api_Handler:
- 个人中心类:挂载
HopeHooks::USER_CENTER_API 接管自定义 action
- 独立前台接口:插件
_show.php + 自建鉴权,或注册路由后由插件处理
- 拦截 rest-api:在
init 钩子里识别方法名并 JsonOut::ok 后结束(注意与核心方法名冲突)
若维护私有分支必须改核心:在 Api_Handler 增加私有方法,方法名即 rest-api 值;需鉴权则调用 Handler 内鉴权方法。
实现入口:system/app/handler/api_handler.php。
联系我们
欢迎通过以下渠道获取帮助、反馈问题或参与社区交流。
联系方式
官方渠道
如何反馈问题
提交问题时请尽量提供:
- Hope CMS 版本(后台首页)
- PHP / MySQL(或 MariaDB)版本
- 当前主题与已启用插件
- 复现步骤与报错信息(可附
content/cache/error.log 相关片段)
安全漏洞请优先通过官方渠道私下反馈,勿在公开 QQ 群 / 论坛直接贴出可被滥用的细节。
获取程序
社区参与
- 在用户论坛发帖互助
- 分享自研主题与插件到应用中心
- 对照官方示例主题
default、示例插件 tips 提交改进建议
文档与参考
站内文档按「入门 → 开发基础 → 主题 → 插件 → 接口」组织;还可参阅:
站内「主题生成器」可快速拼装主题 PHP 片段。
软件许可证
Hope CMS(希望CMS)核心代码按 Apache License 2.0 发布。部分捆绑的第三方库可能采用各自许可证,以其目录内说明为准。