2.1 插件模块三类型与挂载位置
把功能挂到导航、挂到用户页、还是插进现有页面,看这一节就能选对。
模块是什么,谁来挂
插件本身只是一堆躺在 source/plugin/标识符/ 里的 PHP 文件,Discuz! 不会自动执行它们。真正把它们叫醒的是插件模块机制:后台插件详情页分三块设置,每块配置「在什么位置、按什么身份、调用哪个文件」。差别本质是挂载目标不同:挂导航条、挂已有设置页、挂系统脚本的执行点。
| 类型 | 挂到哪里 | 脚本后缀 | 典型用途 |
|---|---|---|---|
| 程序链接 | 导航、菜单 | .inc.php |
加一个入口页 |
| 扩展项目 | 用户中心、后台固定栏 | .inc.php |
在已有页面插入一块 |
| 程序脚本 | 系统脚本执行过程 | .class.php |
不新增页面,改现有行为 |
打个比方:程序链接是新开一扇门,扩展项目是在墙上开一扇窗,程序脚本是在水管上装过滤器。
一个程序链接类模块的最简文件形态,就是模块名加后缀:
<?php
// source/plugin/hello/hello.inc.php ← 后台模块名填 hello
defined('IN_DISCUZ') or exit('Access Denied');
$msg = 'Hello, Discuz!';
include template('hello');
模块名必须和 .inc.php 的文件名一字不差,这是 404 的头号来源。
类型一:程序链接类
这一类负责把插件挂到站点的导航体系上,后台能配的位置有:
| 挂载位置 | 出现的地方 |
|---|---|
| 主导航项目 | 站点顶部主导航 |
| 主导航-插件菜单 | 主导航某项的二级菜单 |
| 顶部导航项目 | 顶部导航条 |
| 底部导航项目 | 页脚导航 |
| 快捷导航项目 | 快捷导航区 |
| 家园导航项目 | 家园(个人空间)导航 |
每个位置可以指派两种目标:一个 URL,或者调用一个插件模块。选了后者,后台让你填模块名,对应 source/plugin/{标识}/{模块名}.inc.php。模块名填 hello,就找 source/plugin/hello/hello.inc.php,生成的链接是 plugin.php?id=标识:模块名。
类型二:扩展项目类
扩展项目不新增页面,而是挂到系统已有的固定位置上。脚本同样以 .inc.php 结尾,但模板是固定文件名,放在 source/plugin/{标识}/template/ 子目录里,与脚本同名。后台提供的挂载位置共 10 个:
| 序号 | 挂载位置 | 出现在 |
|---|---|---|
| 1 | 个人设置 | 用户中心 → 设置 |
| 2 | 个人资料 | 用户中心 → 资料 |
| 3 | 个人积分 | 用户中心 → 积分 |
| 4 | 站点帮助 | 帮助类页面 |
| 5 | 我的帖子 | 用户中心 → 帖子 |
| 6 | 门户管理 | 门户后台 |
| 7 | 论坛管理-基本 | 后台 → 论坛 → 基本 |
| 8 | 论坛管理-工具 | 后台 → 论坛 → 工具 |
| 9 | 管理中心 | 后台插件栏新增管理模块 |
| 10 | 管理中心-列表链接 | 管理中心的远程链接(X3.1 起) |
「固定文件名 + 与脚本同名」这条最容易踩坑。脚本叫 mytools.inc.php,模板就必须是 template/mytools.htm。写错的表现是页面一片空白,控制台没有任何提示。
类型三:程序脚本类
程序脚本不负责出页面,而是插进系统脚本的执行过程里:
| 挂载位置 | 说明 |
|---|---|
| 页面嵌入(普通版) | 桌面版模板里的 {hook/钩子名} |
| 页面嵌入(手机版) | 手机版模板里的同名钩子 |
| 特殊主题 | 帖子特殊主题标识(投票、悬赏那一套) |
脚本以 .class.php 结尾,写成一个类,类名和钩子名有严格对应关系。普通版用 plugin_ 前缀,手机版用 mobileplugin_ 前缀。完整骨架与调用时机见 2.3、2.4。
三类模块对照
横向比一次:程序链接和扩展项目都用 .inc.php,区别在于前者的模板名你自己定(通过 include template() 指定),后者是固定名放在 template/ 子目录。前两者都是「用户点进来才执行」,程序脚本是「系统在执行点自动调用」,不写模板。
决策表:我想把功能挂哪儿
| 我要做的事 | 选哪类 | 挂在哪 |
|---|---|---|
| 加一个独立页面(兑换、抽奖、工具箱) | 程序链接 | 主导航项目 |
| 只给管理员用的操作面板 | 程序链接 | 主导航项目 + 使用等级 |
| 在用户中心加一块设置 | 扩展项目 | 个人设置 |
| 在用户资料页加自定义内容 | 扩展项目 | 个人资料 |
| 在后台加一个配置页 | 扩展项目 | 管理中心 |
| 给帖子内容前后加东西 | 程序脚本 | 页面嵌入 + 对应钩子 |
| 统计或拦截删除操作 | 程序脚本 | 页面嵌入 + 删除类钩子 |
| 改写提示文案、拦截输出 | 程序脚本 | 页面嵌入 + 消息与输出类钩子 |
| 只是个跳转,不需要页面 | 程序链接 | 填 URL,不选模块 |
口诀:要出页面用 .inc.php,不出页面插钩子用 .class.php。
使用等级不等于权限校验
每个模块都能在后台设一个「使用等级」,比如超级版主、管理员。但这个设置只是菜单层面的显示与初步过滤,程序内部仍需自行校验权限。
原因很直接:用户可以手工构造 URL 访问模块。菜单里看不见入口,不代表 URL 打不开。所以模块脚本第一件事是查身份:
<?php
if (!defined('IN_DISCUZ')) {
exit('Access Denied');
}
// $_G['uid'] 非 0 即已登录;$_G['adminid'] 1~3 为管理身份
if (!$_G['adminid']) {
showmessage('抱歉,您没有权限使用此功能');
}
这段放在 source/plugin/标识/模块名.inc.php 的开头。少这一行,模块就等于对全站注册用户开放。
常见坑
| 现象 | 原因 | 处理 |
|---|---|---|
| 后台模块保存后前台不显示 | 插件未启用或缓存没更新 | 启用插件;更新缓存 |
| 扩展项目页面空白无报错 | 模板文件名不对 | 严格按 template/与脚本同名.htm |
| 页面出现裸 PHP 源码 | 模板没走 template() |
一律用 include template() |
| 菜单点进去 404 | 模块名和文件名不一致 | 模块名 = .inc.php 的文件名 |
| 手机版没有效果 | 只写了 plugin_ 类 |
补 mobileplugin_ 类 |
| 普通用户也能打开管理页 | 只靠后台等级设置 | 模块内校验 $_G['adminid'] |
小结
三类模块对应三种意图:程序链接新开门,扩展项目开窗,程序脚本装过滤器。选型只看一件事——这功能需不需要自己出一张页面。需要就 .inc.php,在导航或扩展位置上挂;不需要就 .class.php,去找对应钩子点。
再强调一次最容易翻车的规则:后台的使用等级只是菜单过滤,权限判断必须写在你自己的模块文件里。
2.2 讲最省事的落地方式:文件一放,plugin.php 直接就能访问。
