FastAdmin 插件开发完整指南
版本:V2.0 | 日期:2026-08-14 | 贯穿案例:guestbook(留言板插件)
来源:FastAdmin 官方开发者文档 doc.fastadmin.net/developer(新版,非旧版看云教程)
说明:本版按官方新版规范编写,后台目录结构、菜单升级、公共函数等与旧版有明显差异,已标注 ✅新版
目录
- 插件开发概述
- 创建插件
- 目录结构详解
- 插件核心类与生命周期
- 插件信息 info.ini
- 插件配置 config.php
- 数据库 install.sql 与 testdata.sql
- 控制器开发
- 模型开发
- 视图开发
- 公共函数与自定义函数
- 行为事件(钩子)
- 多语言
- 后台管理功能
- 创建菜单(含升级)
- 打包插件
- 发布前测试与常见问题
一、插件开发概述
FastAdmin 基于 ThinkPHP5 + Bootstrap,插件(官方称"应用插件")是其核心扩展机制。所有插件存放在根目录 addons/ 下,一个插件一个目录,目录名 = 插件标识。
✅新版规范:
- 插件标识只能使用小写字母,至少 3 个字符,建议只使用英文单词或拼音首字母
- 开发前建议先到官方插件标识检测工具验证是否可用:https://www.fastadmin.net/developer/idcheck.html
插件 = 前台功能(controller/model/view/lang,运行在插件目录内)+ 后台管理(application/public 目录覆盖根目录)。
生命周期:安装 → 启用 → 运行 → 禁用 → 卸载 →(升级),每个环节都有对应方法可挂载逻辑。
二、创建插件
2.1 命令行一键创建
cd /var/www/yoursite/ # think 文件所在目录(项目根目录)
php think addon -a guestbook -c create生成的基础结构:
addons/guestbook/
├── Guestbook.php # 插件核心类(标识首字母大写,必需)
├── config.php # 插件配置文件
├── controller/
│ └── Index.php # 默认前台控制器
└── info.ini # 插件信息文件(必需)2.2 验证创建成功
- 前台访问
http://你的域名/addons/guestbook,出现欢迎提示即成功 - 后台「插件管理 → 本地插件」能看到该插件
三、目录结构详解
addons/guestbook/ # 插件标识,全小写
├── application/ # (可选)覆盖根目录 application —— 后台管理功能
│ └── admin/
│ ├── controller/
│ │ └── guestbook/ # ✅新版:后台控制器按【插件标识】分子目录
│ │ ├── Index.php
│ │ └── Message.php
│ ├── lang/
│ │ └── zh-cn/
│ │ └── guestbook/ # ✅新版:后台语言包同样按插件标识分目录
│ │ ├── index.php
│ │ └── message.php
│ ├── model/
│ │ └── guestbook/ # ✅新版:后台模型按插件标识分目录
│ │ └── Message.php
│ └── view/
│ └── guestbook/ # ✅新版:后台视图按插件标识分目录
│ ├── index/
│ └── message/
├── assets/ # 前端资源 → 复制到 /public/assets/addons/guestbook/
├── controller/ # 前台控制器目录
├── lang/ # 前台语言包目录(zh-cn.php / en.php)
├── library/ # ✅新版:插件自定义类目录(如第三方类库)
├── model/ # 前台模型目录
├── public/ # (可选)覆盖根目录 public
│ └── assets/
│ └── js/
│ └── backend/
│ └── guestbook/ # ✅新版:后台 JS 按插件标识分目录
│ ├── index.js
│ └── message.js
├── view/ # 前台视图目录
├── wxapp/ # ✅新版:微信原生小程序源码目录(如有)
├── uniapp/ # ✅新版:Uniapp 源码目录(如有)
├── licenses/ # ✅新版:依赖开源项目的版权文件目录(如有)
├── Guestbook.php # 插件核心类(必需,首字母大写)
├── bootstrap.js # 插件 JS 启动文件(可选)
├── LICENSE # 插件版权文件
├── config.html # ✅新版:自定义插件配置视图模板(可选)
├── config.php # 插件配置(✅新版:可选,不存在时不显示「配置」按钮)
├── info.ini # 插件信息文件(必需)
├── install.sql # 建表 SQL(✅新版:可选,安装时导入)
└── testdata.sql # ✅新版:测试数据 SQL(存在时安装完提示是否导入)关键规则:
| 目录 | 行为 | 注意 |
|---|---|---|
controller/lang/model/view | 前台 MVC,原地运行 | 不复制不移动 |
application/ public/ | 覆盖根目录对应文件 | 安装/卸载时自动文件冲突检测,冲突提示用户 |
assets/ | 复制到 /public/assets/addons/插件名/ | 不检测冲突;视图用 __ADDON__ 指向 |
Guestbook.php | 核心类 | 命名 = 标识首字母大写 |
bootstrap.js | 启动 JS | 启用后合并进 /public/assets/js/addons.js,可用 Fast/Backend/Lang 全局对象 |
🚨 特别注意(新版安全红线):
application不允许新增其它模块,只允许使用自带的index、api、admin模块public和assets目录下不允许任何 php/asp/jsp 等服务端脚本文件
四、插件核心类与生命周期
文件:addons/guestbook/Guestbook.php,命名空间 addons\guestbook,继承 think\Addons。
<?php
namespace addons\guestbook;
use app\common\library\Menu;
use think\Addons;
/**
* guestbook 插件核心类
*/
class Guestbook extends Addons
{
/**
* ✅新版推荐:菜单定义用类属性,install/upgrade 复用
* 子菜单 name 必须以 插件标识/ 开头!
*/
protected $menu = [
[
'name' => 'guestbook', // 首个菜单标识必须和插件标识相同
'title' => '留言板管理',
'icon' => 'fa fa-comments', // FontAwesome 图标
'ismenu' => 1, // 是否为菜单
'weigh' => 1, // 权重,越大越靠前
'remark' => '留言板管理描述', // 菜单描述
'sublist' => [
['name' => 'guestbook/index', 'title' => '查看留言'],
['name' => 'guestbook/add', 'title' => '添加留言'],
['name' => 'guestbook/edit', 'title' => '编辑留言'],
['name' => 'guestbook/del', 'title' => '删除留言'],
['name' => 'guestbook/multi', 'title' => '批量操作'],
],
],
];
public function install()
{
Menu::create($this->menu);
return true;
}
public function uninstall()
{
Menu::delete('guestbook');
return true;
}
public function enable()
{
Menu::enable('guestbook');
return true;
}
public function disable()
{
Menu::disable('guestbook');
return true;
}
/**
* ✅新版:插件升级方法(菜单变更时自动升级)
*/
public function upgrade()
{
Menu::upgrade('guestbook', $this->menu);
return true;
}
}✅新版四件套 → 五件套:install / uninstall / enable / disable / upgrade(菜单升级)。菜单有变更时,Menu::upgrade('插件标识', 菜单数组) 自动完成升级。
五、插件信息 info.ini
name = guestbook
title = 留言板
intro = 一个简单易用的留言板插件
author = 胖虎哥
website = https://www.fastadmin.net
version = 1.0.0
state = 0| 字段 | 说明 |
|---|---|
| name | 插件标识(与目录名一致) |
| title | 插件名称 |
| intro | 插件介绍 |
| author | 作者 |
| website | 作者网站 |
| version | 版本号(打包 zip 名 = 插件名-版本号.zip,升级时改它) |
| state | 开启状态(0/1,框架维护) |
六、插件配置 config.php
✅新版:config.php 为可选文件,不存在时后台不显示「配置」按钮;存在时后台「插件管理 → 配置」读写它。如需自定义配置界面,可加 config.html 视图模板。
返回配置项数组,每项字段:name / title / type / content / value / rule / msg / tip / ok / extend
<?php
return [
[
'name' => 'switch',
'title' => '是否开启留言审核',
'type' => 'switch',
'content' => [],
'value' => '1',
'rule' => 'required',
'msg' => '',
'tip' => '开启后新留言需后台审核',
'ok' => '',
'extend' => '',
],
[
'name' => 'page_size',
'title' => '每页显示条数',
'type' => 'number',
'content' => [],
'value' => '10',
'rule' => '',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => '',
],
[
'name' => 'theme',
'title' => '主题色',
'type' => 'select',
'content' => ['default' => '默认', 'dark' => '深色'],
'value' => 'default',
'rule' => '',
'msg' => '',
'tip' => '',
'ok' => '',
'extend' => '',
],
];type 支持:string / text / number / select / radio / checkbox / switch / array / file / image 等。
读取配置:get_addon_config('guestbook')。
七、数据库
7.1 install.sql(建表)
✅新版:install.sql 为可选。仅包含 SQL 语句,表前缀用 __PREFIX__ 占位符,安装导入时自动替换:
CREATE TABLE IF NOT EXISTS `__PREFIX__guestbook` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL DEFAULT '' COMMENT '昵称',
`email` varchar(100) NOT NULL DEFAULT '' COMMENT '邮箱',
`content` text NOT NULL COMMENT '留言内容',
`status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态:1=显示,0=隐藏',
`createtime` int(10) NOT NULL DEFAULT '0' COMMENT '创建时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='留言板';卸载删表用 uninstall.sql(可选):
DROP TABLE IF EXISTS `__PREFIX__guestbook`;7.2 testdata.sql(测试数据)✅新版
存在此文件时,安装完插件会提示是否导入测试数据:
INSERT INTO `__PREFIX__guestbook` (`name`, `email`, `content`, `status`, `createtime`) VALUES
('测试用户1', 'test1@example.com', '第一条测试留言', 1, 1700000000),
('测试用户2', 'test2@example.com', '第二条测试留言', 1, 1700000001);八、控制器开发
前台控制器继承 think\addons\Controller:
<?php
namespace addons\guestbook\controller;
use think\addons\Controller;
class Index extends Controller
{
public function index()
{
$this->view->assign('pageTitle', __('Guestbook'));
$list = db('guestbook')
->where('status', 1)
->order('id desc')
->paginate(get_addon_config('guestbook')['page_size'] ?? 10);
$this->view->assign('list', $list);
return $this->view->fetch();
}
public function add()
{
if ($this->request->isPost()) {
$name = trim($this->request->post('name'));
$content = trim($this->request->post('content'));
if (!$name) {
$this->error(__('Please input your name'));
}
if (!$content) {
$this->error(__('Please input your content'));
}
$data = [
'name' => $name,
'content' => $content,
'status' => get_addon_config('guestbook')['switch'] ? 0 : 1,
'createtime' => time(),
];
db('guestbook')->insert($data)
? $this->success(__('Submit success'))
: $this->error(__('Submit failed'));
}
return $this->view->fetch();
}
}九、模型开发
前台模型:
<?php
namespace addons\guestbook\model;
use think\Model;
class Guestbook extends Model
{
protected $name = 'guestbook';
protected $autoWriteTimestamp = 'int';
protected $createTime = 'createtime';
protected $updateTime = false;
}十、视图开发
模板位于 view/控制器/方法.html,资源路径用 __ADDON__(指向 /public/assets/addons/guestbook/):
<link rel="stylesheet" href="__ADDON__/css/style.css">
<script src="__ADDON__/js/index.js"></script>列表页 view/index/index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>{$pageTitle}</title>
</head>
<body>
<h1>{:__('Guestbook')}</h1>
<a href="{:addon_url('guestbook/index/add')}">{:__('Add')}</a>
<table border="1" cellpadding="6">
<tr>
<th>{:__('Name')}</th>
<th>{:__('Content')}</th>
<th>{:__('Create time')}</th>
</tr>
{volist name="list" id="vo"}
<tr>
<td>{$vo.name}</td>
<td>{$vo.content}</td>
<td>{$vo.createtime|date='Y-m-d H:i'}</td>
</tr>
{/volist}
</table>
{$list->render()}
</body>
</html>常用标签:{volist} {if} {foreach} {$var} {:函数()} {$vo.field|modifier}
十一、公共函数与自定义函数
11.1 自定义函数 ✅新版
插件自定义函数放 addons/guestbook/helper.php,函数名必须以插件标识开头,且外围加 function_exists 判断:
<?php
// addons/guestbook/helper.php
if (!function_exists('guestbook_custom')) {
function guestbook_custom($str)
{
return 'test' . $str;
}
}在核心类中加载(添加后需后台清缓存生效):
/**
* 应用初始化
*/
public function appInit()
{
require_once __DIR__ . '/helper.php';
}11.2 内置函数
| 函数 | 作用 | 示例 |
|---|---|---|
addon_url() | 生成插件 URL | addon_url('guestbook/index/index', ['id'=>1]) |
get_addon_list() | 已安装插件列表 | 二维数组 |
get_addon_info($name) | 插件基础信息 | name/title/version/state... |
get_addon_config($name) | 插件配置键值数组 | ['switch'=>'1'] |
get_addon_fullconfig($name) | 插件完整配置项 | 含 title/type/rule 等 |
set_addon_config($name, $config) | 写配置 | bool |
set_addon_fullconfig($name, $config) | 写完整配置 | bool |
set_addon_info($name, $array) | 修改插件信息 | bool |
get_addon_instance($name) | 插件核心类单例 | 对象 |
addon_url 参数:$url(插件标识/控制器/方法)|$vars(变量,:name 用于伪静态)|$suffix(是否加后缀)|$domain(是否带域名):
$url1 = addon_url('guestbook/index/index'); // /addons/guestbook/index/index
$url2 = addon_url('guestbook/index/index', ['id' => 123]); // /addons/guestbook/index/index?id=123
$url3 = addon_url('guestbook/index/index', [':name' => 'x', 'id' => 123], true, true); // 带域名11.3 框架内置函数 ✅新版
插件中可直接调用 FastAdmin 框架内置函数,如:
cdnurl()图片补全addtion()附加关联数据check_cors_request()跨域检测xss_clean()清理 XSS
完整列表见官方文档:https://doc.fastadmin.net/doc/1263.html
十二、行为事件(钩子)
通过在核心类中定义约定方法挂载行为,框架自动识别调用:
| 方法名 | 触发时机 |
|---|---|
appInit | 应用初始化(常用:加载 helper.php) |
moduleInit | 模块初始化 |
userSidenavAfter | 会员中心侧边栏渲染后(返回 HTML 追加菜单) |
userRegisterEnd | 用户注册完成后 |
userLoginAfter | 用户登录成功后 |
siteConfigInit | 站点配置初始化 |
示例(会员中心侧边栏,模板放 view/hook/user_sidenav_after.html):
public function userSidenavAfter()
{
$request = Request::instance();
$data = [
'actionname' => strtolower($request->action()),
'controllername' => strtolower($request->controller()),
];
return $this->fetch('view/hook/user_sidenav_after', $data);
}十三、多语言
语言包文件
addons/guestbook/lang/zh-cn.php
addons/guestbook/lang/en.php<?php
// zh-cn.php
return [
'Guestbook' => '留言板',
'Add' => '添加留言',
'Submit' => '提交留言',
'Name' => '昵称',
'Content' => '留言内容',
'Submit success' => '留言提交成功,感谢您的参与!',
'This is %s, base on %s' => '这是%s,基于%s',
];输出方式
// 控制器
$title = __('Guestbook');
$desc = __('This is %s, base on %s', 'FastAdmin', 'ThinkPHP5');<!-- 视图 -->
<h1>{:__('Guestbook')}</h1>切换语言
- URL 参数:
/addons/guestbook/?lang=en(强制指定) - Cookie:
setcookie('think_var', 'en')(后续请求保持) - 自适应:默认按浏览器语言;
application/config.php的lang_switch_on = false可关闭
注意事项
- 语言包键名不区分大小写
- 未定义键原样输出,不报错
%s占位符按顺序替换- 改了语言包没生效 → 清
runtime/缓存
十四、后台管理功能
一键创建CURD
php think crud -t 完整表名 -c 控制器名 -u 1
目录规范(✅新版:按插件标识分子目录)
addons/guestbook/application/admin/
├── controller/guestbook/Index.php # 后台控制器
├── model/guestbook/Message.php # 后台模型
├── lang/zh-cn/guestbook/index.php # 后台语言包
└── view/guestbook/index/index.html # 后台视图
addons/guestbook/public/assets/js/backend/guestbook/index.js # 后台 JS后台控制器示例
<?php
namespace app\admin\controller\guestbook; // ✅新版命名空间
use app\common\controller\Backend;
class Index extends Backend
{
protected $model = null;
public function _initialize()
{
parent::_initialize();
$this->model = model('guestbook');
}
public function index()
{
$this->request->filter(['strip_tags', 'trim']);
if ($this->request->isAjax()) {
[$where, $sort, $order, $offset, $limit] = $this->buildparams();
$list = $this->model->where($where)->order($sort, $order)->paginate($limit);
return json(['total' => $list->total(), 'rows' => $list->items()]);
}
return $this->view->fetch();
}
public function del($ids = '')
{
if ($ids) {
$this->model->where('id', 'in', $ids)->delete();
$this->success('删除成功');
}
$this->error('参数错误');
}
}十五、创建菜单(含升级)
菜单配置(✅新版字段:ismenu / weigh / remark)
protected $menu = [
[
'name' => 'guestbook', // 首个菜单标识必须和插件标识相同
'title' => '留言板管理',
'icon' => 'fa fa-comments',
'ismenu' => 1, // 是否为菜单
'weigh' => 1, // 权重,越大越靠前
'remark' => '留言板管理描述',
'sublist' => [
// ✅新版:子菜单 name 必须以 插件标识/ 开头
['name' => 'guestbook/index', 'title' => '查看留言'],
['name' => 'guestbook/add', 'title' => '添加留言'],
['name' => 'guestbook/del', 'title' => '删除留言'],
['name' => 'guestbook/multi', 'title' => '批量操作'],
],
],
];多级菜单
sublist 内继续嵌套 sublist(支持无限级,建议层级不宜过多),每级可带 icon / ismenu / weigh。
生命周期联动(五件套)
public function install() { Menu::create($this->menu); return true; }
public function uninstall() { Menu::delete('guestbook'); return true; }
public function enable() { Menu::enable('guestbook'); return true; }
public function disable() { Menu::disable('guestbook'); return true; }
public function upgrade() { Menu::upgrade('guestbook', $this->menu); return true; } // ✅新版Menu::upgrade('插件标识', 菜单数组) 自动完成菜单升级(新增/变更规则)。
十六、打包插件
一键打包(推荐)
cd /var/www/yoursite/
php think addon -a guestbook -c package产物:runtime/addons/guestbook-1.0.0.zip(版本号取自 info.ini)
手动打包(命令行失败才用)
进入 addons/guestbook/ 目录 → 选中所有文件(含隐藏文件)→ 压缩为 zip。
🚨 打包必清清单(✅新版新增项)
- 务必移除
.addonrc文件 - 务必移除
.DS_Store、.git、.svn等文件或目录 - 移除无关文件、代码、注释、类、图片、JS 等资源
- 不要在
addons/目录下直接压缩插件文件夹(包内多一层目录,后台无法安装)
打包前自检清单
- [ ] 目录结构规范(Guestbook.php / info.ini 齐全)
- [ ] ✅新版:后台文件按插件标识子目录放置(controller/guestbook/ 等)
- [ ] install.sql / testdata.sql 与实际表结构一致
- [ ] lang 有 zh-cn 和 en
- [ ] 无调试代码、无 .addonrc/.git/.svn/.DS_Store
- [ ] public/assets 无 php 等服务端脚本
- [ ] 五件套齐全(install/uninstall/enable/disable/upgrade)
- [ ] 本地走完安装→启停→卸载→重装→升级 全流程
十七、发布前测试与常见问题
完整测试流程
- 后台「插件管理 → 本地安装」上传 zip
- 验证:菜单生成、数据表创建、测试数据导入提示、前台
/addons/guestbook可访问 - 前台功能测试:列表、提交、校验、分页
- 多语言测试:
?lang=en切换 - 启用/禁用:菜单跟随显隐
- 卸载:菜单删除、uninstall.sql 执行
- 重装:确认无残留、权限菜单重新勾选
- 升级测试:改版本号重打包 → 后台升级 → 验证
upgrade()菜单升级
常见问题速查
| 问题 | 原因/解决 |
|---|---|
| zip 装不上 | 压缩时多了外层目录 → 进插件目录选所有文件压缩 |
| 安装报索引错误 | 残留错误菜单 → 「权限管理 → 规则菜单」删除 |
| 卸载重装后没权限 | 管理组权限菜单需重新勾选 |
| 后台菜单 404 | 后台控制器位置/命名空间错误(✅新版命名空间 app\admin\controller\guestbook\) |
| 语言不生效 | 清 runtime/ 缓存 |
| 自定义函数不生效 | helper.php 是否已 require + 后台清缓存 |
| 前台 404 | 控制器/方法名大小写、伪静态配置 |
| assets 不加载 | 视图路径要用 __ADDON__ 前缀 |
附:新版官方文档更多章节
以下主题官方文档另有专章,需要时可深入:
- 数据库(79)、配置(80)、控制器(81)、视图(82)、测试数据(83)、全局 JS(84)
- 行为事件(87)、模型(93)、第三方类(96)、伪静态(98)
- 跨域配置(393)、定时任务(701)、命令行(710)、缓存(cache)、并发处理(4390)、整合插件(2523)
官方文档入口:https://doc.fastadmin.net/developer
评论区
还没有人评论