Skip to content

🧩 后端总览

SunAdmin 后端采用最新的 Laravel 13 框架 + 模块化设计,业务模块集中在 modules,公共基础能力集中在 app/Coreapp/Support

🧭 本章怎么读

后端文档建议按“先理解入口,再理解分层,再深入专项能力”的顺序阅读。第一次接触项目时,不建议直接跳到模型、支付或 AI 章节,因为这些能力都依赖路由、认证、响应、分层和配置约定。

阅读阶段建议阅读目标
第1步后端总览知道后端源码放在哪里、模块如何组织、一次请求会经过哪些层
第2步模块与分层、模块配置先理解 Controller、接口业务动作、Service、Dao、Model 各写什么;再看 module.json、安装记录、依赖声明等模块清单字段
第3步模块安装与运维、模块资源发布会安装/卸载模块、生成运行包、撰写 publish-manifest.json
第4步路由与认证会新增 Admin / Api 接口,理解公开接口、登录接口、认证中间件
第5步接口响应与异常会返回统一结构,会处理业务失败、未登录、无权限、参数错误
第6步权限与菜单会给后台页面、按钮、接口补权限和菜单数据
第7步系统配置、数据字典会维护系统配置、字典、初始化数据和缓存刷新
第8步模型机制会编写模型、scope、accessor、mutator、cast 和关联
第9步附件上传与存储会接入上传、存储驱动、公开访问路径和富文本资源
第10步缓存与队列会处理缓存失效、热点缓存、异步任务和队列 worker
第11步支付基础能力、支付业务对接会处理支付接入、统一支付单、退款单、渠道回调和业务处理器
第12步AI、MCP / 公共函数与工具会维护 AI 配置、知识库、MCP 工具和项目公共辅助函数

🗺️ 文档用途地图

你想做什么优先看继续看
新增一个接口模块与分层模块配置、路由与认证、接口响应与异常、权限与菜单
不知道某个注解什么意思代码注解路由与认证
新增列表搜索条件模型机制模块与分层、接口响应与异常
新增后台菜单和按钮权限权限与菜单路由与认证、系统配置
新增系统配置项系统配置数据字典、缓存与队列
新增字典选项数据字典系统配置
新增上传入口或存储驱动附件上传与存储接口响应与异常、系统配置
安装、卸载或排查模块模块安装与运维模块配置、模块资源发布
撰写或排查 publish-manifest.json模块资源发布模块安装与运维
接入支付通道支付基础能力支付业务对接、模块安装与运维
业务模块创建支付单或处理回调支付业务对接支付基础能力、缓存与队列
接入 AI 对话或知识库AI系统配置、缓存与队列
创建 MCP 工具或 AI Agent 工具MCPAI
不知道某个函数在哪里公共函数与工具后端总览、模块与分层

🧪 技术栈

  • PHP ^8.3
  • Laravel ^13.0
  • Laravel Sanctum ^4.3
  • Spatie Route Attributes ^1.28
  • Laravel AI ^0.6.3
  • Laravel MCP ^0.7.0
  • Yansongda Pay 3.7.4

🧷 公共基础能力

路径说明
app/Core/AttributesInjectOpenGetOpenPost 等项目注解
app/Core/Http项目 Request、FormRequest、控制器基类、中间件
app/Core/Dao/BaseDao.phpDao 通用查询、保存、列表分页、状态变更
app/Core/Database/SunAdminBuilder.phpEloquent Builder 扩展,提供 filter()listData()
app/Core/Models/BaseModel.php模型基类,挂载日期、媒体 URL、筛选 scope 能力
app/Core/Support/ApiResponse.php统一 code/message/data 响应结构
app/Support/ModuleRegistry.php模块、路由扫描目录与模块启动注册器注册

🏗️ 模块结构(以System模块为例)

text
modules/System
├─ module.json                  模块包信息,提供 title、slug、version、resources 等配置
├─ Ai/
│  └─ Tools/                    Laravel AI Agent 工具适配,自动发现
├─ Application/
│  ├─ Actions/                  接口业务动作,承接一个接口要完成的具体业务步骤
│  ├─ Jobs/                     队列任务
│  └─ Services/                 业务服务、外部集成、支付、AI 运行编排
├─ Dao/                         数据访问层
├─ Database/Seeders/            模块初始数据
├─ Domain/
│  ├─ Enums/                    枚举
│  └─ Models/                   Eloquent 模型
├─ Http/
│  ├─ Controllers/Admin/        后台接口控制器
│  ├─ Controllers/Api/          用户端接口控制器
│  └─ Requests/                 FormRequest
├─ Mcp/
│  └─ Tools/                    Laravel MCP Server 工具,自动发现
└─ Providers/                   模块启动注册器,接入路由、配置、事件等

module.json 只保存模块包信息。路由前缀优先由 slug 推导;普通业务模块必须在 system_modules 中存在安装记录且 status=1,才会注册模块启动注册器和路由。详细说明见 模块配置

🛣️ 典型请求链路

  1. 路由注解将请求分发到 Controller。
  2. Controller 通过 #[Inject] 注入接口业务动作 Action 或 Service。
  3. FormRequest 负责字段校验,复杂场景可用 validated('scene')
  4. Action 组织本次接口的业务步骤,调用 Service / Dao。
  5. Dao 通过模型和 SunAdminBuilder 查询数据。
  6. Controller 返回 success() 或抛出业务异常。

示意流程:

🪜 代码分层约定

场景推荐位置
只做参数接收和响应Controller
一个接口需要串联多个服务/DaoApplication/Actions
可复用业务能力或外部集成Application/Services
单表或聚合查询Dao
字段转换、关联、状态 scopeDomain/Models
稳定业务状态值Domain/Enums

🧑‍💻 常见开发任务示例

以“新增一个后台文章列表接口”为例,推荐按下面顺序落代码:

  1. modules/System/Http/Controllers/Admin/Article 新增或扩展控制器方法,使用路由注解声明 URI。
  2. modules/System/Http/Requests/Admin/Article 新增请求类,声明校验规则。
  3. modules/System/Application/Actions/Admin/Article 编写 Action,负责完成这个接口对应的复杂业务动作,例如需要串联多个服务/Dao。(如果只是常规CRUD操作,可以在控制器中通过Dao集成的能力完成,无需再创建一层Actions处理)
  4. modules/System/Dao/Article 编写查询方法,或统一走 filter()getList()save()Dao 集成能力。
  5. modules/System/Domain/Models/Article 补充 scopeTitle()scopeStatus() 等筛选条件。
  6. 如果是后台菜单页面,需要在菜单管理中维护菜单、按钮和权限码,如果要做数据迁移还需要在 Seeder 初始相关数据。

以文章列表控制器为例,形态通常是:

php
use App\Core\Attributes\Inject;
use App\Core\Http\Controllers\ApiController;
use Spatie\RouteAttributes\Attributes\Get;
use Spatie\RouteAttributes\Attributes\Group;
use Spatie\RouteAttributes\Attributes\Post;
use Modules\System\Dao\Article\ArticleDao;
use Modules\System\Http\Requests\Admin\Article\ArticleRequest;

#[Group(prefix: 'article/list')]
class ArticleController extends ApiController
{
    #[Inject]
    protected ArticleDao $dao;

    #[Get('index')]
    public function index()
    {
        $filters = $this->request()->pick([
            ['title', ''],
            ['status', ''],
        ]);

        return success($this->dao->getList(
            $filters,
            '*',
            ['sort' => 'desc', 'id' => 'desc']
        ));
    }
    
    #[Post('save')]
    public function save(ArticleRequest $form)
    {
        $this->dao->save($form->validated('save'));

        return success();
    }
}

示例代码用途说明

代码用途
#[Group(prefix: 'article/list')]给当前控制器所有路由统一增加 article/list 前缀,避免每个方法重复写完整路径
#[Inject] protected ArticleDao $dao;自动注入 ArticleDao 实例
#[Get('index')]声明 index() 方法为 GET 接口
public function index()文章列表入口,通常用于表格列表、分页查询、条件筛选
$this->request()->pick([...])从当前请求中只提取允许的筛选字段,并为字段设置默认值
$this->dao->getList(...)调用 Dao 的列表查询方法,统一输出 list/count/page_no/page_size 分页结构
$filters传给 Dao 的筛选条件,由模型 scopeFilter() 处理数据过滤
'*'查询字段,表示查询全部字段;真实业务中可按需改成字段数组减少返回体积
['sort' => 'desc', 'id' => 'desc']排序规则,先按 sort 倒序,再按 id 倒序,保证列表顺序稳定
#[Post('save')]声明 save() 方法为 POST 接口,适合保存、修改这类写入操作
public function save(ArticleRequest $form)保存接口入口,并让 Laravel 自动注入 ArticleRequest
$form->validated('save')获取 ArticleRequestsave 场景的校验参数,并返回数据集给业务层
$this->dao->save(...)调用 Dao 的新增/更新方法,通常根据主键是否存在决定创建还是修改

按照这段代码组合后,如果当前控制器位于后台 Admin 控制器目录下,接口路径通常会形成类似:

text
GET  /adminapi/system/article/list/index
POST /adminapi/system/article/list/save

更详细的用法说明请继续往下阅读相关章节