注解

介绍

特点

注解是 Hyperf 非常强大的一项功能,也是 MineAdmin 到处使用的功能。

程序可以通过注解的形式减少很多的配置,以及实现很多非常方便的功能。

什么是注解什么是注释?

在解释注解之前我们需要先定义一下 注解注释 的区别:

  • 注释:给程序员看,帮助理解代码,对代码起到解释、说明的作用。
  • 注解:给应用程序看,用于元数据的定义,单独使用时没有任何作用,需配合应用程序对其元数据进行利用才有作用。

注解如何书写

由于,我们已经使用了 PHP 8.0 及以上版本,我们可以使用php自带的原生注解,故我们也只讲原生注解使用方法。

注解配置

/config/autoload/annotations.php 可配置注解收集目录、收集器及忽略项

我们还是看控制器的代码,我们发现代码里存在两句:

  • #[Controller(prefix: "foo")]
  • #[GetMapping("index")]

以上就是使用和书写注解的方式,由 #[] 组成,方括号内的内容则是注解内容

<?php

declare(strict_types=1);
namespace App\Foo\Controller;

use Mine\MineController
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\GetMapping;
use Psr\Http\Message\ResponseInterface;

#[Controller(prefix: "foo")]
class FooController extends MineController {
    
    #[GetMapping("index")]
    public function index(): ResponseInterface
    {
        return $this->success('操作成功', [ 'data' => 'hello MineAdmin!']);
    }
}

路由注解

提示

系统内所有的 http 访问都是以注解形式定义的路由。根据系统的开发规范,要放弃过去的配置文件注册路由的形式,转而使用注解来注册路由。

相比配置文件使用注解来注册路由有以下好处:

  • 找控制器文件方便,不需要再打开相应的配置文件查找具体的控制器文件
  • 找路由方便,不需要对比控制器文件和配置文件相互印证,只需要通过全局搜索注解路由即可
  • 控制器即是路由文件,减少了配置文件
  • 对新手友好,可以更快掌握开发方式

类路由注解

类路由使用 #[Controller] 注解来注册路由,使用 prefix 指定类路由的前缀

/**
 * 该类的访问前缀则为:system/user
 */
#[Controller(prefix: "system/user")]
class UserController extends MineController
{
    //todo...
}

方法路由注解

  • #[PostMapping] POST请求路由注解
  • #[GetMapping] GET请求路由注解
  • #[DeleteMapping] DELETE请求路由注解
  • #[PutMapping] PUT请求路由注解

提示

其他请求注解方式请参考 hyperf 路由open in new window 章节

/**
 * 定义控制器访问前缀
 */
#[Controller(prefix: "system/user")]
class UserController extends MineController
{
    /**
     * 定义操作路由
     * 该方法的访问路径为:system/user/index,请求方式:GET
     */
    #[GetMapping("index")]
    public function index()
    {
        return $this->success('hello world');
    }
}

路由命名规范

规范

路由命名规范为:模块名/业务名/操作名

整个系统的路由定义规范皆是如此,尽量遵守约定,可以减少项目后续中的麻烦。

系统内置注解

MineAdmin 在开发之初就规划了几个注解,我们可以在开发中调用这些注解来帮助完成业务开发

登录验证注解

注解名

  • #[Auth]

说明

用户必须登录后才可以访问某个接口

使用范围

  • √ 代表可用
  • x 代表不可用
方法
类使用后,该类所有方法都将验证若类未使用,仅方法使用,只对该方法检查

注解参数

参数名说明默认值
scene场景名,需要验证登录的场景'default'

使用示例

// 引入注解
use Mine\Annotation\Auth;

#[Auth]
class UserController extends MineController
{
    // ...    
}

// 或者

class FooController extends MineController
{
    #[Auth]
    public function index()
    {
        // ...
    }
}

权限验证注解

注解名

  • #[Permission]

说明

只允许有某接口权限的用户访问(会附带其登录验证)

使用范围

  • √ 代表可用
  • x 代表不可用
方法
x
-仅能对方法使用

注解参数

参数名说明默认值
code权限代码标识,支持验证多个权限-
where验证条件:AND, OROR

使用示例

// 引入注解
use Mine\Annotation\Permission;

class FooController extends MineController
{
    /**
     * 验证一个权限,通过即可访问
     */
    #[Permission("system:foo:index")]
    public function index(): ResponseInterface
    {
        //...
    }

    /**
     * 验证多个权限,全部通过才可访问
     */
    #[Permission("system:foo:save, system:foo:update", "AND")]
    public function save(): ResponseInterface
    {
        //...
    }

    /**
     * 验证多个权限,其中一个通过即可访问
     */
    #[Permission("system:foo:index, system:foo:read", "OR")]
    public function read(): ResponseInterface
    {
        //...
    }
}

角色验证注解

注解名

  • #[Role]

说明

只允许有用某个角色的用户访问(会附带其登录验证)

使用范围

  • √ 代表可用
  • x 代表不可用
方法
x
-仅能对方法使用

注解参数

参数名说明默认值
code角色代码标识,支持验证多个角色-
where验证条件:AND, OROR

使用示例

// 引入注解
use Mine\Annotation\Role;

class FooController extends MineController
{
    /**
     * 验证一个角色,通过即可访问
     */
    #[Role("superAdmin")]
    public function index(): ResponseInterface
    {
        //...
    }

    /**
     * 验证多个角色,全部通过才可访问
     */
    #[Role("ceo, cfo", "AND")]
    public function save(): ResponseInterface
    {
        //...
    }

    /**
     * 验证多个角色,其中一个通过即可访问
     */
    #[Role("cto, cfo", "OR")]
    public function read(): ResponseInterface
    {
        //...
    }
}

操作日志注解

注解名

  • #[OperationLog]

说明

使用后会记录用户在后台请求某接口的参数、返回值、用户信息等

使用范围

  • √ 代表可用
  • x 代表不可用
方法
x
-仅能对方法使用

注解参数

提示

如果未传参数,请配合 #[Permission] 注解使用

参数名说明默认值
menuName菜单名称默认值:未定义菜单,搭配 #[Permission] 注解使用后,会自动获取菜单名称

使用示例

// 引入注解
use Mine\Annotation\OperationLog;

class UserController extends MineController
{
    /**
     * 新增用户
     */
    #[Permission("system:user:save"), OperationLog]
    public function save(): ResponseInterface
    {
        //...
    }

    /**
     * 获取用户列表
     */
    #[OperationLog("用户列表")]
    public function list(): ResponseInterface
    {
        //...
    }
}

数据库事务注解

注解名

  • #[Transaction]

说明

使用后会自动启动事务、提交。执行失败自动回滚。

使用范围

  • √ 代表可用
  • x 代表不可用
方法
x
-仅能对方法使用

注解参数

参数名说明默认值
retry重试次数1

使用示例

// 引入注解
use Mine\Annotation\Transaction;

// 忽略其他代码

/**
 * 新增用户,使用事务注解,失败重试 2 次
 */
#[Transaction(2)]
public function save(): MineModel
{
    //...
}

防止重复提交注解

注解名

  • #[Resubmit]

说明

对接口使用后会在3秒内(默认值)禁止再次访问

使用范围

  • √ 代表可用
  • x 代表不可用
方法
x
-仅能对方法使用

注解参数

参数名说明默认值
second要禁止的秒数3
message提示的信息-

使用示例

// 引入注解
use Mine\Annotation\Resubmit;

// 忽略其他代码

/**
 * 新增用户,3秒内禁止重复提交
 */
#[Resubmit]
public function save(): MineModel
{
    //...
}

清除缓存注解

注解名

  • #[DeleteCache]

说明

用于更新、删除数据操作后,执行清除缓存操作,只需要指定缓存key即可

使用范围

  • √ 代表可用
  • x 代表不可用
方法
x
-仅能对方法使用

注解参数

参数名说明默认值
keys要清除的缓存key,支持多个,每个key以逗号隔开;支持 通配符:* 清除缓存-

使用示例

// 引入注解
use Mine\Annotation\DeleteCache;

// 忽略其他代码

/**
 * 在更新完信息后,使用删除缓存注解,自动清除指定缓存
 */
#[DeleteCache("crontab,loginInfo:*")]
public function updateInfo(): ResponseInterface
{
    //...
}

Excel相关注解

注解名

  • #[ExcelData]
  • #[ExcelProperty]

说明

注解服务用于 数据导出为ExcelExcel导入到数据库

#[ExcelData] 使用范围

  • √ 代表可用
  • x 代表不可用
方法
x
仅能对类使用,声明类为 ExcelData-

#[ExcelProperty] 使用范围

  • √ 代表可用
  • x 代表不可用
方法属性
xx
-x声明导出列映射数据库字段属性

#[ExcelData] 注解参数

#[ExcelProperty] 注解参数

参数说明默认值
value显示在excel第一行的列名称-
index设置excel列的显示顺序,从0开始-
width设置单元格的宽度-
align设置单元格的对齐方式,有 left, center, right 可选left
headColor设置表头单元格字体颜色,十六进制,例如 00FF00,xlswriter只支持整行设置-
headBgColor设置表头单元格背景颜色,十六进制,例如 00FF00,xlswriter只支持整行设置-
color设置表体单元格字体颜色,十六进制,例如 00FF00,xlswriter只支持整行设置-
bgClor设置表体单元格背景颜色,十六进制,例如 00FF00,xlswriter只支持整行设置-
dictName设置字典标识(后台字典管理里查看),数据在导出时自动翻译成对应标签数据-
dictData设置自定义字典数据,数据在导出时自动翻译成对应标签数据-

dictData说明

比如,数据库里的数据是 1、2、3 之类的固定类别数据,那么在定义 dictData 要以 key 是数据 value 是标签的形式来定义:

#[ExcelProperty(value: "数据类别", index: 1, dictData:[ 1 => '类别1', 2 => '类别2', 3 => '类别3'])]
public string $type;

使用示例

<?php
namespace App\System\Dto;

use Mine\Interfaces\MineModelExcel;
use Mine\Annotation\ExcelData;
use Mine\Annotation\ExcelProperty;

/**
 * 用户数据对象类
 */
#[ExcelData]
class UserDto implements MineModelExcel
{
    #[ExcelProperty(value="用户名", index=0, width=20)]
    public string $username;

    #[ExcelProperty(value="昵称", index=1, width=15)]
    public string $nickname;
    
    #[ExcelProperty(value="手机", index=2, width=15)]
    public string $phone;
}

依赖代理注解

注解名

  • #[DependProxy]

说明

无需修改源代码,可无感平替某个类或接口。在注解收集目录内,申明即生效。

使用范围

  • √ 代表可用
  • x 代表不可用
方法
x

注解参数

参数名说明默认值
values类型:array,被替换目标类的名称-
provider类型:string,提供服务目标类的名称默认为当前类

使用示例

// 引入注解
use Mine\Annotation\DependProxy;
use Mine\Interfaces\UserServiceInterface;

/**
 * 实现无感替换 mineadmin 自带的登录 退出 功能
 */
#[DependProxy(values: [ UserServiceInterface::class )]
class loginHandler implements UserServiceInterface
{
    public function login(\Mine\Vo\UserServiceVo $vo)
    {
        // todo...
    }
    
    public function logout()
    {
        // todo...
    }
}

远程通用接口启停注解

注解名

  • #[RemoteState]

说明

无需修改源代码,可无感平替某个类或接口。

使用范围

  • √ 代表可用
  • x 代表不可用
方法
x

注解参数

参数名说明默认值
state类型:bool,远程通用接口允许状态true