1.4 设计新插件与插件 XML 清单
从零把一个插件登记到后台,并把它的配置打包成能分发的 XML。
1.4.1 第一步:打开开发者模式
后台默认不给「设计新插件」的入口。在站点根目录的 config/config_global.php 末尾加一行:
$_config['plugindeveloper'] = 1;
保存后进后台刷新,插件列表里才会出现「设计新插件」这类入口。
开发期还有个很实用的技巧:把这个值改成 2 并更新缓存,打开任意页面后在源码里搜索 <hook> 标记,就能看到该页面预留了哪些钩子,比翻文档猜钩子名靠谱。注意是临时排查用的,别忘了改回 1。
1.4.2 第二步:后台「设计新插件」
进后台 → 应用 → 插件 → 设计新插件,要填的核心就两项:
| 字段 | 填什么 |
|---|---|
| 插件名称 name | 显示给用户看的中文名,可以改 |
| 唯一标识符 identifier | 目录名、类名前缀,全站唯一,定了就别改 |
标识符规矩和设计新模板时一样:命名规则同 PHP 变量,字母或下划线开头,只含字母、数字、下划线;不能和现有插件重复;建议一次定好;别取太短,两个字母的标识符在几十万站点里早被抢光了。
填完保存,系统会在 source/plugin/ 下生成同名目录并往插件配置表插一条记录,插件的「壳」就有了。后台没自动建目录的话,手动建成这样:
source/plugin/myplugin/
├── index
├── core.inc.php
└── template/
├── core.htm
└── mobile/
index 是空的防目录浏览文件,建好后刷新后台即可在模块配置页选到它。
1.4.3 XML 清单是什么
插件配置写完,后台可以「导出」成一个 XML 文件,即插件清单,里面装着插件的元信息、模块定义、变量配置,以及安装/卸载/升级要跑的脚本名。
它解决的是分发问题:把 XML 和插件目录一起打包发给用户,导入 XML 就完成安装,不用手动建表、不用手动配模块。X5.0 里还有一类是页面组件/模块组件的导出 XML,在 /template/xxx/portal/diyxml/page/ 和 module/ 下,那是给模板用的。
1.4.4 清单节点逐个讲
| 节点 | 作用 |
|---|---|
installfile |
安装脚本文件名 |
uninstallfile |
卸载脚本文件名 |
upgradefile |
升级脚本文件名 |
checkfile |
安装/卸载/升级前的检测脚本 |
enablefile / disablefile |
插件开启/关闭时执行(X3.1 新增) |
license |
授权协议文本,支持 Discuz! 代码,站长同意后才能安装 |
intro |
插件介绍文本,显示在插件页 |
version |
当前版本号,同时是兼容性声明 |
importfile |
导入论坛数据:smilies 表情、styles 风格 |
version 是一字段两用:既是插件版本,又是兼容性声明。多版本用逗号分隔,比如 X3,X3.5,X5.0,系统靠它判断这个包能不能装到当前站点。X5.0 不兼容 X3.5 及更早版本,纯 X5 的插件建议就写 X5.0。
importfile 只接受两种值:smilies(表情)和 styles(风格),多个用逗号分隔。
1.4.5 安装脚本怎么写
安装脚本里用 runquery() 执行 SQL,三条硬约定:表名可以直接写 "cdb_"(系统自动替换成实际前缀);结束时输出 $finish = TRUE;;脚本放插件根目录,文件名就是 installfile 里写的那个。
<?php
// source/plugin/myplugin/install.php
runquery("CREATE TABLE IF NOT EXISTS cdb_myplugin_log (
logid mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
uid mediumint(8) unsigned NOT NULL DEFAULT '0',
nickname varchar(60) NOT NULL DEFAULT '',
note varchar(255) NOT NULL DEFAULT '',
dateline int(10) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (logid),
KEY uid (uid)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;");
runquery("INSERT INTO cdb_common_setting VALUES ('myplugin_enabled', '1')");
$finish = TRUE;
这段在用户点「安装」时执行一次。
1.4.6 升级脚本与卸载脚本
升级脚本可以用两个内置变量判断版本跳跃:
<?php
// source/plugin/myplugin/upgrade.php
if ($fromversion == '1.0' && $toversion == '1.1') {
runquery("ALTER TABLE cdb_myplugin_log ADD COLUMN ip varchar(45) NOT NULL DEFAULT ''");
}
$finish = TRUE;
$fromversion 是旧版本,$toversion 是新版本。跨度大时用多个 if 串起来,让用户从任意旧版升上来都能走通。
卸载脚本有一条版本差异:X3.1 起卸载脚本不再支持页面跳转及 $finish。写跳转、写 $finish = TRUE; 都不起作用,脚本跑完就结束。老插件照抄安装脚本结构会出问题,卸载脚本就老老实实清数据、删设置。
checkfile 是安装、卸载、升级前跑的检测脚本,适合检查 PHP 扩展、目录可写性。
1.4.7 一个最小可用的 XML 骨架
实际用的时候从后台导出再改,比手写靠谱。下面是最小结构:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<item>
<![CDATA[我的插件]]>
<identifier>myplugin</identifier>
<version>X5.0</version>
<installfile>install.php</installfile>
<uninstallfile>uninstall.php</uninstallfile>
<upgradefile>upgrade.php</upgradefile>
<checkfile>check.php</checkfile>
<license><![CDATA[本插件遵循授权协议,站长安装即表示同意]]></license>
<intro><![CDATA[这是一个示例插件]]></intro>
</item>
</root>
identifier 必须和 source/plugin/ 下的目录名一致,installfile 这些必须是实际存在的文件名,少一个安装就会中断。
1.4.8 文件名里的语言标识
一个省事的细节:XML 文件名以 SC_GBK、SC_UTF8、TC_BIG5、TC_UTF8 结尾时,后台直接显示成对应字样——「简体」「繁体」「UTF8」这些;不带后缀则显示原始文件名。给不同语言版本打包时加上后缀,用户一眼就能分清。
1.4.9 本节要点
- 先在
config/config_global.php加$_config['plugindeveloper'] = 1;。 - 后台「设计新插件」填名称与唯一标识符,规则同 PHP 变量、不可重复、一次定好、别太短。
- 在
source/plugin/{标识}/建目录并放空index文件。 version兼作兼容性声明,importfile只收smilies和styles,enablefile/disablefile是 X3.1 新增。- 脚本三条约定:
runquery()执行 SQL、表名写"cdb_"、结束输出$finish = TRUE;。 - 升级脚本用
$fromversion/$toversion判断;卸载脚本从 X3.1 起不支持跳转和$finish。
第一篇到此把「机制 → 目录 → 运行环境 → 登记打包」串了一遍。第二篇开始写第一个能跑起来的插件。
