主题
插件开发实战
在上一篇 快速入门 中,我们已经成功搭建了一个基础插件并完成安装。本章将带你从零开始,通过一个完整的实战案例,手把手教你开发一个功能完善的 CatchAdmin 后台模块插件。
开始之前
在开始开发之前,请确保你已经:
- 完成了 快速入门 的学习
- 熟悉 Laravel 的基本概念(路由、控制器、模型)
- 了解 Vue.js 的基础知识(可选,用于前端页面开发)
目录结构约定
开发一个完整的后台模块插件时,我们推荐遵循以下约定的目录结构:
├─test # 插件根目录
│ ├─resource # 资源目录(可选)
│ │ └─views # Vue 视图文件目录
│ ├─config # 配置文件目录(可选)
│ ├─migrations # 数据库迁移目录(可选)
│ ├─routes # 路由定义目录(可选)
│ ├─src # 源代码目录(核心)
│ │ ├─Http # HTTP 层
│ │ │ ├─Controllers # 控制器
│ │ │ └─Requests # 表单验证(可选)
│ │ └─Models # 数据模型(可选)
│ ├─hook.php # 生命周期钩子
│ ├─composer.json # Composer 配置
│ └─README.md # 说明文档目录说明
| 目录/文件 | 必需 | 说明 |
|---|---|---|
src/ | 存放插件的核心源代码 | |
composer.json | 定义插件的依赖和元信息 | |
hook.php | 插件生命周期钩子,详见 钩子文档 | |
routes/ | 可选 | 定义插件的 API 路由 |
migrations/ | 可选 | 数据库迁移文件 |
resource/views/ | 可选 | Vue 前端页面文件 |
config/ | 可选 | 插件配置文件 |
TIP
什么时候需要这些目录?
- 开发完整后台模块:上述所有目录基本都需要用到
- 开发简单功能插件:根据实际需求选择性添加
- 开发 API 接口:必须按照约定的目录结构进行开发
CatchAdmin 的插件本质上就是一个 Composer 包,因此你可以根据实际需求灵活组织代码结构。
接下来,我们将使用上一篇创建的 test/test 插件,一步步开发一个完整的后台模块。
第一步:创建数据迁移
大多数插件都需要存储数据,因此我们首先创建数据库迁移文件。
生成迁移文件
执行以下命令,在插件目录中创建迁移文件:
shell
php artisan make:migration CreateUser --path=packages\test\test\migrations命令执行后,会在 packages/test/test/migrations 目录下生成一个迁移文件:

📚 不熟悉数据迁移?
如果你对 Laravel 的数据迁移不太了解,可以先阅读官方文档:Laravel 数据迁移
编写迁移文件
打开生成的迁移文件,添加表结构定义:
php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('test_user', function (Blueprint $table) {
$table->id();
$table->string('name')->comment('名称');
$table->string('mobile')->comment('手机号');
$table->string('avatar')->nullable()->comment('头像');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('test_user');
}
};执行迁移
运行以下命令创建数据表:
shell
php artisan migrate --path=packages\test\test\migrations\执行成功后,使用数据库客户端(如 Navicat)查看,可以看到 test_user 表已创建:

第二步:创建模型
数据表创建完成后,我们需要创建对应的 Eloquent 模型来操作数据。
生成模型文件
执行 Laravel 的模型生成命令:
shell
php artisan make:model TestUser该命令会在 app/Models 目录下生成模型文件:

移动到插件目录
将生成的模型文件移动到插件的 src/Models 目录下(如果目录不存在,请先手动创建):

⚠️ 注意命名空间
移动文件后,必须修改命名空间以匹配新的目录位置!详见 常见问题 - 命名空间相关
修改后的模型内容如下:
php
<?php
namespace Test\Test\Models;
use Illuminate\Database\Eloquent\Model;
class TestUser extends Model
{
protected $table = 'test_user';
protected $fillable = [
'name', 'mobile', 'avatar'
];
}第三步:创建控制器
控制器负责处理 HTTP 请求,是连接前端和数据的桥梁。
创建目录结构
按照约定,在 src 目录下创建以下目录结构:
src/
└─Http/
└─Controllers/然后在 Controllers 目录中创建 TestUserController.php:

编写控制器代码
php
<?php
namespace Test\Test\Http\Controllers;
use Catch\Base\CatchController;
class TestUserController extends CatchController
{
public function index()
{
return ['test_user' => 'has no users'];
}
}第四步:配置路由
控制器创建完成后,还需要配置路由才能访问。
创建路由文件
在插件根目录创建 routes 目录,并在其中创建 api.php 文件:

在 api.php 中添加路由定义:
php
\Illuminate\Support\Facades\Route::get('/test/user', [\Test\Test\Http\Controllers\TestUserController::class, 'index']);重新安装插件
⚠️ 重要步骤
每次修改插件的路由、配置等文件后,都需要重新安装插件才能生效!详见 常见问题 - 安装相关
shell
# 先卸载旧版本
composer remove test/test --ignore-platform-reqs
# 再安装新版本
composer require test/test:* --ignore-platform-reqs启动开发服务器
shell
php artisan serve验证接口
打开浏览器访问 http://127.0.0.1:8000/test/user:

🎉 恭喜! 如果看到返回的 JSON 数据,说明接口已经成功运行了!
第五步:集成 CatchAdmin 功能
到目前为止,我们已经有了一个可以访问的基础接口。接下来,我们将让插件与 CatchAdmin 深度集成,实现:
- ✅ 身份认证
- ✅ 权限控制
- ✅ Vue 前端页面
- ✅ 自动生成菜单
5.1 添加身份认证
为了让插件接口需要登录才能访问,我们需要添加身份认证中间件。
修改 routes/api.php 文件:
php
\Illuminate\Support\Facades\Route::prefix(config('catch.route.prefix'))
->middleware([
\Catch\Middleware\AuthMiddleware::class // 身份认证中间件
])
->group(function(){
\Illuminate\Support\Facades\Route::get('test/user',
[\Test\Test\Http\Controllers\TestUserController::class, 'index']);
});重新安装插件后,访问 http://127.0.0.1:8000/api/test/user:

看到 Unauthenticated 提示,说明身份认证中间件已生效!🔐
5.2 添加权限控制
在身份认证的基础上,我们还可以添加权限控制,确保只有拥有相应权限的用户才能访问接口。
继续修改 routes/api.php:
php
\Illuminate\Support\Facades\Route::prefix(config('catch.route.prefix'))
->middleware([
\Catch\Middleware\AuthMiddleware::class, // 身份认证
\Modules\Permissions\Middlewares\PermissionGate::class // 权限控制
])
->group(function(){
\Illuminate\Support\Facades\Route::get('test/user',
[\Test\Test\Http\Controllers\TestUserController::class, 'index']);
});5.3 添加 Vue 前端页面
CatchAdmin 使用 Vue 作为前端框架。好消息是,插件的 Vue 页面无需编译,可以实现即插即用!
创建视图目录
在插件根目录创建以下目录结构:
resource/
└─views/
└─user/
└─index.vue
编写 Vue 页面
在 index.vue 中添加内容:
vue
<script>
export default {
name: "index.vue"
}
</script>
<template>
<div>这是测试用户页面</div>
</template>
<style scoped>
</style>访问 Vue 页面
安装插件后,可以通过以下 URL 访问 Vue 文件内容:
http://127.0.0.1:8000/api/plugins/test/test/user/index📝 URL 规则说明
| 部分 | 说明 |
|---|---|
api/plugins | 固定前缀 |
test/test | 插件包名 |
user/index | 对应 resource/views/user/index.vue |
注意:必须先安装插件,URL 才能生效!

5.4 使用钩子自动创建菜单
最后一步,我们使用插件钩子在安装时自动创建后台菜单。更多钩子用法请参考 生命周期钩子。
编辑钩子文件
找到插件根目录的 hook.php 文件:

在 afterInstall 方法中添加菜单创建代码:
php
public function afterInstall(array $context): void
{
Plugin::createMenus([
Plugin::createMenu('测试插件', '/test', 'Test\Test', children: [
Plugin::createMenu('测试用户', 'user', 'Test\Test',
controller: 'TestUser', controllerMethod: 'index', type: 2,
component: Plugin::view('test/test', 'user.index')
)
])
]);
}⚠️ module 参数说明
module 参数必须填写插件的根命名空间(如 Test\Test),这用于标识菜单归属于哪个插件。

重新安装并查看效果
shell
composer remove test/test --ignore-platform-reqs
composer require test/test:* --ignore-platform-reqs刷新后台页面,你将看到新创建的菜单:

🎉 大功告成! 你已经成功开发了一个完整的 CatchAdmin 后台模块插件!
卸载插件
卸载插件非常简单,只需执行以下命令:
shell
composer remove test/test --ignore-platform-reqs使用钩子清理数据
为了在卸载时自动清理插件创建的菜单等数据,可以在 hook.php 的 afterUninstall 方法中添加清理逻辑:
php
public function afterUninstall(array $context): void
{
// 删除该插件创建的所有菜单
Permissions::where('module', $context['namespace'])->delete();
}💡 提示
$context['namespace']会自动获取插件的根命名空间- 上述代码会删除该插件的所有菜单,你可以根据实际需求调整删除逻辑
总结
通过本教程,你已经学会了:
- 目录结构约定 - 插件的标准目录组织方式
- 数据库迁移 - 在插件中创建和管理数据表
- 模型与控制器 - 编写业务逻辑代码
- 路由配置 - 定义 API 接口
- 中间件集成 - 添加身份认证和权限控制
- Vue 页面开发 - 创建无需编译的前端页面
- 生命周期钩子 - 在安装/卸载时执行自定义逻辑
遇到问题?请查看 常见问题。
现在,你可以根据实际需求,开发更复杂的插件功能了!🚀

