Skip to content

3.6 控制器开发 ​

概述

控制器是 HTTP 请求的入口,负责参数获取、调用 Logic 层、返回 JSON 响应。通过 #[Permission] 和 #[Log] 注解实现权限校验和操作日志。

控制器文件位置 ​

text
app/controller/ExampleController.php

完整代码(来自项目实际代码) ​

php
<?php
declare(strict_types=1);

namespace app\controller;

use app\BaseController;           // 控制器基类
use app\logic\ExampleLogic;       // 案例演示业务逻辑
use app\attribute\Log;            // 操作日志注解
use app\attribute\Permission;     // 权限校验注解
use think\response\Json;          // JSON 响应类型

/**
 * 案例演示管理控制器
 *
 * 负责案例演示相关的 HTTP 接口入口,包括:
 * - 分页列表、列表查询、详情查询;
 * - 新增、修改、删除、批量删除;
 * - 导入、导出。
 *
 * 具体业务逻辑委托给 ExampleLogic 处理,
 * 并通过注解统一实现日志记录与权限校验。
 */
class ExampleController extends BaseController
{
    /**
     * 案例演示业务逻辑层
     *
     * @var ExampleLogic
     */
    protected ExampleLogic $logic;

    /**
     * 控制器初始化
     *
     * 在每次请求进入控制器方法前执行,用于实例化业务逻辑层。
     * ThinkPHP 会自动调用此方法(在构造函数之后)。
     *
     * @return void
     */
    protected function initialize(): void
    {
        $this->logic = new ExampleLogic();
    }

    // ... 以下为各接口方法
}

控制器模式

每个控制器遵循固定模式:

  1. initialize() 中实例化 Logic
  2. 每个方法标注 #[Log] 和 #[Permission] 注解
  3. 简单调用 parent::_index() / _detail() / _add() 等通用方法
  4. 复杂操作(如导入导出)自行处理并 try-catch
php
    /**
     * 案例演示分页列表
     *
     * GET /example/page
     * 对应权限:sys:example:page
     *
     * 调用 BaseController::_index(),内部流程:
     * 1. 合并分页参数(pageNo/pageSize)和普通参数
     * 2. 调用 ExampleLogic::pageList()
     * 3. 返回标准分页响应
     *
     * @return Json
     */
    #[Log('案例演示-查询分页记录', Log::TYPE_QUERY)]
    #[Permission('sys:example:page', '案例演示分页')]
    public function page(): Json
    {
        return parent::_index($this->logic);
    }

    /**
     * 案例演示列表
     *
     * GET /example/list
     * 返回全量数据(不分页),适用于下拉选择等场景。
     *
     * @return Json
     */
    #[Log('案例演示-查询列表', Log::TYPE_QUERY)]
    public function list(): Json
    {
        return parent::_list($this->logic);
    }

    /**
     * 案例演示详情
     *
     * GET /example/detail/{id}
     *
     * 调用 BaseController::_detail(),内部流程:
     * 1. 调用 ExampleLogic::detail($id)
     * 2. 查询为空返回 404
     * 3. 自动补全文件字段域名、枚举显示名
     * 4. 触发 afterDetail 钩子
     *
     * @param int $id 案例演示ID
     * @return Json
     */
    #[Log('案例演示-查询详情', Log::TYPE_QUERY, '查询案例演示ID:{id}')]
    public function detail(int $id): Json
    {
        return parent::_detail($this->logic, $id);
    }

    /**
     * 添加案例演示
     *
     * POST /example/add
     * 对应权限:sys:example:add
     *
     * 调用 BaseController::_add(),内部流程:
     * 1. 调用 ExampleLogic::add($data)
     * 2. 触发 beforeAdd/afterAdd 钩子
     * 3. 返回新记录 ID
     *
     * @return Json
     */
    #[Log('案例演示-新增记录', Log::TYPE_ADD, '新增案例演示:{name}')]
    #[Permission('sys:example:add', '添加案例演示')]
    public function add(): Json
    {
        // getJsonBody() 获取前端 POST 提交的 JSON 数据
        return parent::_add($this->logic, $this->getJsonBody());
    }

    /**
     * 更新案例演示
     *
     * PUT /example/update
     * 对应权限:sys:example:update
     *
     * 从 JSON 请求体中读取 id,若缺失则直接返回失败。
     *
     * @return Json
     */
    #[Log('案例演示-修改记录', Log::TYPE_UPDATE, '修改案例演示ID:{id}')]
    #[Permission('sys:example:update', '修改案例演示')]
    public function update(): Json
    {
        $data = $this->getJsonBody();
        $id = $data['id'] ?? 0;

        // 校验 ID 参数
        if (empty($id)) {
            return $this->fail('缺少id参数');
        }

        return parent::_edit($this->logic, $id, $data);
    }

    /**
     * 删除案例演示
     *
     * DELETE /example/delete/{id}
     * 对应权限:sys:example:delete
     *
     * 调用 BaseController::_remove(),内部流程:
     * 1. 调用 ExampleLogic::delete($id)
     * 2. 触发 beforeDelete/afterDelete 钩子
     * 3. 设置 is_delete=1(软删除)
     *
     * @param int $id 案例演示ID
     * @return Json
     */
    #[Log('案例演示-删除记录', Log::TYPE_DELETE, '删除案例演示ID:{id}')]
    #[Permission('sys:example:delete', '删除案例演示')]
    public function delete(int $id): Json
    {
        return parent::_remove($this->logic, $id);
    }

    /**
     * 批量删除案例演示
     *
     * DELETE /example/batchDelete
     * 对应权限:sys:example:delete
     *
     * 从 JSON 请求体中读取 ids 数组。
     *
     * @return Json
     */
    #[Log('案例演示-批量删除记录', Log::TYPE_DELETE)]
    #[Permission('sys:example:delete', '删除案例演示')]
    public function batchDelete(): Json
    {
        $ids = $this->getJsonBody()['ids'] ?? [];
        return parent::_batchRemove($this->logic, $ids);
    }

    /**
     * 导入案例演示
     *
     * POST /example/import
     * 对应权限:sys:example:import
     *
     * 处理流程:
     * 1. 从请求中获取上传文件
     * 2. 校验文件扩展名(仅 xls、xlsx)
     * 3. 调用 ExampleLogic::import() 解析并导入
     *
     * @return Json
     */
    #[Log('案例演示-导入数据', Log::TYPE_IMPORT)]
    #[Permission('sys:example:import', '导入案例演示')]
    public function import(): Json
    {
        $file = $this->request->file('file');
        if (!$file) {
            return $this->fail('请选择文件');
        }

        $ext = strtolower($file->getOriginalExtension());
        if (!in_array($ext, ['xls', 'xlsx'])) {
            return $this->fail('仅支持 xls、xlsx 格式的文件');
        }

        try {
            $result = $this->logic->import($file->getRealPath());

            $msg = empty($result['errors'])
                ? "成功导入 {$result['count']} 条数据"
                : "成功导入 {$result['count']} 条,失败 " . count($result['errors']) . " 条";

            return $this->success($result, $msg);
        } catch (\Exception $e) {
            return $this->fail('导入失败: ' . $e->getMessage());
        }
    }

    /**
     * 导出案例演示
     *
     * GET /example/export
     * 对应权限:sys:example:export
     *
     * @return Json
     */
    #[Log('案例演示-导出数据', Log::TYPE_EXPORT)]
    #[Permission('sys:example:export', '导出案例演示')]
    public function export(): Json
    {
        try {
            $filePath = $this->logic->export($this->getParams());
            return $this->success($filePath, '导出成功');
        } catch (\Exception $e) {
            return $this->fail('导出失败: ' . $e->getMessage());
        }
    }
}

注解说明 ​

#[Log] 操作日志注解 ​

php
#[Log('案例演示-新增记录', Log::TYPE_ADD, '新增案例演示:{name}')]
//      │                      │               │
//      │                      │               └── 描述(支持 {param} 占位符)
//      │                      └── 操作类型
//      └── 操作标题

#[Permission] 权限注解 ​

php
#[Permission('sys:example:add', '添加案例演示')]
//              │                      │
//              │                      └── 权限名称
//              └── 权限编码

BaseController 通用方法 ​

方法用途内部调用
_index($logic)分页查询$logic->pageList()
_list($logic)全量列表$logic->allList()
_detail($logic, $id)详情查询$logic->detail($id)
_add($logic, $data)新增$logic->add($data)
_edit($logic, $id, $data)修改$logic->update($id, $data)
_remove($logic, $id)删除$logic->delete($id)
_batchRemove($logic, $ids)批量删除$logic->batchDelete($ids)

小蚂蚁云团队 · 提供技术支持