MacCMS源码结构分析
本文结合 MacCMS V10 源码(magicblack/maccms10),梳理它的整体架构、目录职责、请求生命周期和几个关键模块,帮助你在对接、采集、排障时知道「代码在哪、怎么跑」。
版本说明
以下结论均基于实际阅读 MacCMS V10 源码得出。框架版本以源码 thinkphp/base.php 里的 THINK_VERSION 常量为准。不同发行版本的行号可能略有差异,涉及行号处仅作定位参考。
概述:MacCMS V10 = ThinkPHP 5.0.24 + MVC
MacCMS V10 是基于 ThinkPHP 5.0.24 的 PHP 应用。源码 thinkphp/base.php 里固定定义了 THINK_VERSION = '5.0.24',整站沿用 ThinkPHP5 的 MVC 分层与模块化约定:
- 入口文件(
index.php/admin.php/api.php/install.php)负责定义常量、做最基础的环境检查,然后把控制权交给框架。 - 业务代码都在
application/下按模块(module)组织,每个模块内部再分controller/model/view。 - 框架本体在
thinkphp/,第三方库在vendor/和extend/,插件在addons/。
三入口对比
MacCMS V10 用多个入口脚本分离前台、后台、API 与安装四类流量。它们都位于源码根目录,差异集中在 BIND_MODULE(绑定模块)常量和各自的特有逻辑上:
| 入口 | BIND_MODULE | ENTRANCE | 特有逻辑 |
|---|---|---|---|
index.php | 'index' | 'index' | 无强制检查 |
api.php | 'api' | 'api' | 无强制检查 |
admin.php | 未定义(define('BIND_MODULE','admin'); 被注释掉) | 'admin' | 强制改名检查(见下方说明) |
install.php | 'install' | 'install' | install.lock 存在则禁止重装;检查 runtime 目录是否可写 |
admin.php 必须改名,否则后台打不开
admin.php 里有一段强制改名检查(位于 install.lock 判断之后、框架引导之前):当请求脚本名里包含 /admin.php 时,直接输出一句「请将后台入口文件 admin.php 改名」并 exit,根本不会把请求交给框架。
if(strpos($_SERVER["SCRIPT_NAME"],'/admin.php')!==false){
echo '请将后台入口文件admin.php改名,避免被黑客入侵攻击';
exit;
}也就是说,用默认的 admin.php 访问后台会被源码直接拦下,后台进不去,必须把 admin.php 改成别人猜不到的文件名后再用新名字访问。index.php 与 api.php 没有这个检查。详见安全加固与部署排障。
环境检查
三个入口(以及 install.php)在脚本开头都有一行 PHP 版本硬检查,只拦 < 5.5 的版本。实际的版本选择口径(composer 要求 >=7.0、推荐 PHP 7.x)见安装教程。
目录结构职责
application 子模块
业务代码全在 application/ 下,按模块(module)组织:
| 目录 | 职责 |
|---|---|
admin | 后台模块,站点管理、采集、配置等后台控制器与视图 |
api | API 模块,含 Provide / Vod 两套接口(见下文「关键模块走读」) |
index | 前台模块,面向访客的影视展示页面 |
common | 公共模块,含 model/Collect.php 等共享模型与采集逻辑 |
install | 安装模块,controller/Index.php + sql/install.sql + sql/initdata.sql + 安装向导视图 |
extra | 配置集合,拆分出的多个 .php 配置文件(见「配置体系」) |
lang | 语言包 |
command | 命令行命令 |
data | 运行期数据,含 install/install.lock(安装锁) |
根级目录
| 目录 | 职责 |
|---|---|
thinkphp | ThinkPHP 5.0.24 框架本体 |
vendor | Composer 第三方依赖 |
extend | 扩展类库 |
addons | 插件目录(见「addons 插件机制」) |
template | 前台/后台模板(模板里可嵌 PHP) |
static / static_new | 静态资源 |
upload | 上传附件(需可写) |
runtime | 框架运行期缓存(需可写) |
请求生命周期
一个请求从入口到控制器,大致经过这些阶段:
- 入口脚本:
index.php/admin.php/api.php定义BIND_MODULE、ENTRANCE等常量,做 PHP 版本与install.lock检查(admin.php还有强制改名检查)。 - 加载框架:入口
require进thinkphp/start.php,启动 ThinkPHP5 引导流程。 - 路由解析:
think\App::run()优先按application/route.php的伪静态规则匹配;未命中则走 TP5 默认的模块/控制器/操作规则。 - 模块分发:
think\App::module()解析出目标模块、控制器、操作,并对控制器名做正则校验(这是 ThinkPHP5 修复历史 RCE 漏洞的关键校验点,详见安全加固)。 - 执行控制器:实例化控制器、调用对应 action,返回响应。
为什么 Provide API 地址是 /api.php/provide/vod/
api.php 绑定了 BIND_MODULE = 'api',而 route.php 里没有为 provide 单独写路由,所以它走的是 TP5 默认的「控制器/操作」规则:/api.php/provide/vod/ 对应 app\api\controller\Provide 控制器的 vod() 方法。详见API接口说明。
关键模块走读
API:Provide 与 Vod 两套
application/api/controller/ 下有两套面向不同场景的接口,返回结构完全不同,别混用:
Provide.php:经典的「资源站/采集提供」接口,地址/api.php/provide/vod/,用于站点间互采、对接空壳影视。支持ac(list/videolist/detail)、from、ids、t、wd等参数。Vod.php:新版自研 REST 接口,地址形如/api.php/vod/get_list,面向 MacCMS 官方自家 App,返回结构与 Provide 不同。
两套接口的参数、返回字段与使用场景,详见API接口说明。
采集:Collect 控制器 + 模型
采集逻辑分布在两处:
application/admin/controller/Collect.php:后台采集入口api(),按mid分发到不同资源类型(1= 视频、2= 文章等)。application/common/model/Collect.php:采集核心模型,包含几个值得注意的点:check_flag():校验cjflag是否等于cjurl的 md5,不匹配就拒绝,防止采集链接被随意伪造。checkCjUrl():SSRF 防护,拒绝host为空或指向127.0.0.1/localhost的采集地址。base64_decode(...):对采集链接里的param附加参数做解码,这是合法的业务用法,不是后门。
采集链接的参数含义与配置方法,详见采集教程。
安装:install 入口 + 模块
install.php 入口 + application/install 模块负责首次安装:读取 install/sql/install.sql、initdata.sql 初始化数据库,检查 runtime 可写性。安装完成后会在 application/data/install/install.lock 写入锁文件,之后三个主入口都会检查这个锁,install.php 发现锁存在则禁止重装。
配置体系
MacCMS 的配置拆成几层:
application/config.php:ThinkPHP5 应用配置,含app_debug/app_trace(生产环境应关闭,见安全加固)。application/database.php:数据库连接配置。application/route.php:伪静态路由规则。application/extra/*.php:MacCMS 自己的配置集合,拆成maccms.php、bind.php(采集分类绑定)、vodplayer.php、vodserver.php、version.php等多个文件。
addons 插件机制
MacCMS V10 支持 addons/ 插件目录,每个插件独立成一个子目录,内部按需包含 controller / model / service / view / lang / assets 等。源码自带四个插件:
| 插件 | 作用 | 大致构成 |
|---|---|---|
adminloginbg | 后台登录页背景 | assets + controller |
aicontent | AI 内容生成 | controller / model / service / view / lang |
mpt | 内容处理相关 | controller / model / service / view / lang |
socialws | 社交 WebSocket 服务 | controller + server,依赖 workerman |
第三方插件要留心
插件是独立于主程序的代码,第三方来源的插件应重点审查后再启用。安全审查方法见安全加固。