注解路由 + ApiDoc接入

安装
复制代码
ApiDoc
composer require hg/apidoc
注解路由
composer require shayvmo/webman-annotations
配置路径
复制代码
ApiDoc
/config/plugin/hg/apidoc/app.php
注解路由
/config/plugin/shayvmo/webman-annotations/annotation.php
配置文件

ApiDoc

复制代码
<?php
return [
    'enable'  => true,
    'apidoc' => [
        // (选配)文档标题,显示在左上角与首页
        'title'              => 'Apidoc',
        // (选配)文档描述,显示在首页
        'desc'               => '',
        // (必须)设置文档的应用/版本
        'apps'           => [
            [
                // (必须)标题
                'title'=>'接口文档',
                // (必须)控制器目录地址
                'path'=>'app\webapi\controller',
                // (必须)唯一的key
                'key'=>'webapi',
                // (选配)该应用是否不允许调试
                'notDebug'=>false,
            ]
        ],
        // (必须)指定通用注释定义的文件地址
        'definitions'        => "app\common\controller\Definitions",
        // (必须)自动生成url规则,当接口不添加@Apidoc\Url ("xxx")注解时,使用以下规则自动生成
        'auto_url' => [
            // 字母规则,lcfirst=首字母小写;ucfirst=首字母大写;
            'letter_rule' => "lcfirst",
            // url前缀
            'prefix'=>"",
        ],
        // (选配)是否自动注册路由
        'auto_register_routes'=>false,
        // (必须)缓存配置
        'cache'              => [
            // 是否开启缓存
            'enable' => false,
        ],
        // (必须)权限认证配置
        'auth'               => [
            // 是否启用密码验证
            'enable'     => false,
            // 全局访问密码
            'password'   => "123456",
            // 密码加密盐
            'secret_key' => "apidoc#hg_code",
            // 授权访问后的有效期
            'expire' => 24*60*60
        ],
        // 全局参数
        'params'=>[
            // (选配)全局的请求Header
            'header'=>[
                // name=字段名,type=字段类型,require=是否必须,default=默认值,desc=字段描述
                ['name'=>'authorization','type'=>'string','require'=>true,'desc'=>'身份令牌Token','default'=>'Bearer+空格+token'],
            ],
            // (选配)全局的请求Query
            'query'=>[
                // 同上 header
            ],
            // (选配)全局的请求Body
            'body'=>[
                // 同上 header
                ['name'=>'lang','type'=>'string','require'=>true,'desc'=>'语言编码','default'=>'zh'],
            ],
        ],
        // 全局响应体
        'responses'=>[
            // 成功响应体
            'success'=>[
                ['name'=>'code','desc'=>'响应码','type'=>'int','require'=>1,'default'=>'200','md'=>'/public/apidoc/docs/HttpError.md'],
                ['name'=>'msg','desc'=>'提示信息','type'=>'string','require'=>1,'default'=>'操作成功'],
                //参数同上 headers;main=true来指定接口Returned参数挂载节点
                ['name'=>'result','desc'=>'响应数据','main'=>true,'type'=>'array','require'=>1,'default'=>[]],
            ],
            // 异常响应体
            'error'=>[
                ['name'=>'code','desc'=>'响应码','type'=>'int','require'=>1,'default'=>'400','md'=>'/public/apidoc/docs/HttpError.md'],
                ['name'=>'msg','desc'=>'提示信息','type'=>'string','require'=>1,'default'=>'操作失败'],
                ['name'=>'result','desc'=>'响应数据','main'=>true,'type'=>'array','require'=>1,'default'=>[]],
            ]
        ],
        //(选配)默认作者
        'default_author'=>'',
        //(选配)默认请求类型
        'default_method'=>'GET',
        //(选配)Apidoc允许跨域访问
        'allowCrossDomain'=>false,
        /**
         * (选配)解析时忽略带@注解的关键词,当注解中存在带@字符并且非Apidoc注解,如 @key test,此时Apidoc页面报类似以下错误时:
         * [Semantical Error] The annotation "@key" in method xxx() was never imported. Did you maybe forget to add a "use" statement for this annotation?
         */
        'ignored_annitation'=>[],

        // (选配)数据库配置
        'database'=>[],
        // (选配)Markdown文档
        'docs'              => [
            [
                'title'=>'HTTP响应编码',
                'children'=>[
                    ['title'=>'code错误码说明','path'=>'/public/apidoc/docs/HttpError.md'],
                    ['title'=>'status错误码说明','path'=>'/public/apidoc/docs/HttpStatus.md'],
                ],
            ]
        ],
        // (选配)接口分享功能
        'share'=>[
            // 是否开启接口分享功能
            'enable'=>true,
            // 自定义接口分享操作,二维数组,每个配置为一个按钮操作
            'actions'=>[
                [
                    // 操作名称
                    'name'=>'下载json',
                    // 点击时触发的方法
                    'click'=>function($shareData,$apiData){
                        $path = "test.word";
                        $jsonFile = fopen(public_path().DIRECTORY_SEPARATOR.$path, "w") or die("Unable to open file!");
                        $txt = json_encode($apiData);
                        fwrite($jsonFile, $txt);
                        fclose($jsonFile);
                        // 返回js给前端执行,内置了downloadFile方法来执行文件下载
                        return 'downloadFile("/'.$path.'","'.$shareData['name'].'");';
                    }
                ]
            ]
        ],
        // (选配)接口生成器配置 注意:是一个二维数组
        'generator' =>[]
    ]
];

注解路由

复制代码
<?php
return [
    // 注解扫描路径, 只扫描应用目录下已定义的文件夹,例如: app/admin/controller 及其下级目录
    'include_paths' => [
        'admin'
    ],
    // requestMapping 允许的请求method
    'allow_methods' => ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'HEAD', 'PATCH'],
    // 忽略解析的注解名称,适用于 php7 使用 doctrine/annotations 解析
    'ignored' => [
        "after", "afterClass", "backupGlobals", "backupStaticAttributes", "before", "beforeClass", "codeCoverageIgnore*",
        "covers", "coversDefaultClass", "coversNothing", "dataProvider", "depends", "doesNotPerformAssertions",
        "expectedException", "expectedExceptionCode", "expectedExceptionMessage", "expectedExceptionMessageRegExp", "group",
        "large", "medium", "preserveGlobalState", "requires", "runTestsInSeparateProcesses", "runInSeparateProcess", "small",
        "test", "testdox", "testWith", "ticket", "uses" , "datetime",
    ]
];
浏览器访问
复制代码
http://你的域名/apidoc/index.html
案例
复制代码
<?php
namespace app\webapi\controller;
use app\middleware\AllowOriginMiddleware;
use app\middleware\AuthTokenMiddleware;
use hg\apidoc\annotation as Apidoc;
use Shayvmo\WebmanAnnotations\Annotations\Middleware;
use Shayvmo\WebmanAnnotations\Annotations\RequestMapping;
use Shayvmo\WebmanAnnotations\Annotations\RestController;

#[Apidoc\Title("轮播图类")]
#[RestController("/webapi/banner")]
#[Middleware(AllowOriginMiddleware::class)]
class Banner {
    #[RequestMapping(["/bannerList"], methods: ['GET', 'POST', 'OPTIONS'])]
    #[Apidoc\Title("轮播图列表")]
    #[Apidoc\Url("/webapi/banner/bannerList")]
    #[Apidoc\Method("POST,GET")]
    #[Apidoc\ParamType("formdata")]
    #[Apidoc\Param("page", type: "string", require: true, default: "1", desc: "页码")]
    #[Apidoc\Param("limit", type: "string", require: true, default: "10", desc: "条数")]
    #[Apidoc\Returned("position", type: "string", default: "position", desc: "位置:home 首页")]
    #[Apidoc\Returned("is_link", type: "string", default: "0", desc: "是否开启链接:0否1是")]
    #[Apidoc\Returned("link", type: "string", default: "https://www.baidu.com", desc: "链接")]
    #[Apidoc\Returned("img", type: "string", default: "/uploads/202402/65d593dd0026.png", desc: "图片")]
    #[Apidoc\Returned("lang", type: "string", default: "zh", desc: "语言")]
    #[Middleware(AuthTokenMiddleware::class)]
    public function bannerList(Request $request): Response
    {
        [$lang] = $request->inputMore([
            ['lang','zh'],
        ],true);
        [$page, $limit,$count] = getPageValue($request);
        $where = [
            ['lang','=',$lang],
            ['is_del','=',0],
        ];
        $list = WebBanner::getPageList($where,[],$page,$limit,'sort','asc');
        if(!empty($list)){
            foreach ($list as &$v){
                $v['img'] = $v['img'] ? sysConfig('site_url').$v['img'] : sysConfig('site_url').'/uploads/tubiao/avatar.png';
            }
            unset($v);
            $count = WebBanner::getCount($where);
        }
        return success(lang($request,'操作成功'),compact('list','count'));
    }
}
文档

ApiDoc

http://docs.apidoc.icu/use/

注解路由

复制代码
一、中间件注解
注:方法会继承类定义的中间件。

类和方法通用,参数中间件类名,单个中间件传入字符串,多个中间件传入字符串数组。

use Shayvmo\WebmanAnnotations\Annotations\Middleware;
use App\third\middleware\SignatureCheckA;

// php74
/**
 * @Middleware(
 *     \App\third\middleware\SignatureCheck::class,
 * )
 */
 
/**
 * @Middleware({
 *   SignatureCheckA::class,
 *   \App\third\middleware\SignatureCheck::class,
 * })
 */

// php8注解
// 单个中间件
#[Middleware(LimitTrafficMiddleware::class)]
// 多个
#[Middleware([LimitTrafficMiddleware::class, \App\third\middleware\SignatureCheck::class])]


// 忽略中间件校验注解
use Shayvmo\WebmanAnnotations\Annotations\MiddlewareIgnore;

// php74
/**
 * @MiddlewareIgnore(
 *     \App\third\middleware\SignatureCheck::class,
 * )
 */
 
/**
 * @MiddlewareIgnore({
 *   SignatureCheckA::class,
 *   \App\third\middleware\SignatureCheck::class,
 * })
 */

// php8注解
// 单个中间件
#[MiddlewareIgnore(LimitTrafficMiddleware::class)]
// 多个
#[MiddlewareIgnore([LimitTrafficMiddleware::class, \App\third\middleware\SignatureCheck::class])]


二、类注解
类注解有控制器注解@RestController和资源路由@ResourceMapping。 资源路由和webman框架原有的资源路由一致。参考:webman路由

控制器注解
use Shayvmo\WebmanAnnotations\Annotations\RestController;
@RestController控制器注解,只有一个参数prefix,表示整个控制器的路由路径前缀,方法路由路径都会拼接该前缀。 传参可以省略键名。

@RestController("/a")
@RestController(prefix="/a")
php8注解

#[RestController("/test1")]
#[RestController(path: "/test2")]
资源路由注解
use Shayvmo\WebmanAnnotations\Annotations\ResourceMapping;
@ResourceMapping资源路由注解,有path 和 allow_methods两个参数 path表示资源路由的路径,allow_methods为指定的资源方法数组,不传指定资源方法时,使用全部资源方法 path传参可以省略键名。

@ResourceMapping(path="/dddd", allow_methods={"index", "show"})
@ResourceMapping("/dddd", allow_methods={"index", "show"})
php8注解

#[ResourceMapping("/test", allow_methods: ["index", "show"])]
#[ResourceMapping(path: "/test2", allow_methods: ["index", "show"])]
注:如果定义了资源路由,会自动忽略类同名方法的方法注解。

附:资源路由方法对照

请求方法	路径	类方法
GET	/test	index
GET	/test/create	create
POST	/test	store
GET	/test/{id}	show
GET	/test/{id}/edit	edit
PUT	/test/{id}	update
DELETE	/test/{id}	destroy
PUT	/test/{id}/recovery	recovery
三、方法注解
方法注解主要是@RequestMapping 以及 @GetMapping、@PostMapping、@PutMapping、@DeleteMapping 四个便捷注解。 定义路由路径 path 和请求方法methods。两个参数均可以传入字符串或数组。 例如path传入数组时,表示多个请求路由路径。methods传入数组时,表示多个请求方法。

注:便捷注解传入路由路径path即可,可以省略键名path,无需传入methods

@RequestMapping(path={"/dddd", "/dddd1"}, methods={"get", "post"})
@GetMapping(path={"/get","/get1"})
@GetMapping({"/get","/get1"})
@PostMapping(path="/post")
@PutMapping(path="/put")
@DeleteMapping(path="/delete")
php8注解

#[RequestMapping("/test1", methods: "get")]
#[RequestMapping(["/test1","/test11"], methods: ["get", "post"])]
#[GetMapping(["/get", "/get1"])]
#[PostMapping(path: "/post")]
#[PutMapping(path: "/put")]
#[DeleteMapping("/delete")]
// 方法注解
use Shayvmo\WebmanAnnotations\Annotations\RequestMapping;
use Shayvmo\WebmanAnnotations\Annotations\GetMapping;
use Shayvmo\WebmanAnnotations\Annotations\PostMapping;
use Shayvmo\WebmanAnnotations\Annotations\PutMapping;
use Shayvmo\WebmanAnnotations\Annotations\DeleteMapping;
相关推荐
BingoGo16 小时前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php
JaguarJack16 小时前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php·服务端
JaguarJack2 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
后端·php·服务端
BingoGo2 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
php
JaguarJack3 天前
告别 Laravel 缓慢的 Blade!Livewire Blaze 来了,为你的 Laravel 性能提速
后端·php·laravel
郑州光合科技余经理3 天前
代码展示:PHP搭建海外版外卖系统源码解析
java·开发语言·前端·后端·系统架构·uni-app·php
QQ5110082853 天前
python+springboot+django/flask的校园资料分享系统
spring boot·python·django·flask·node.js·php
WeiXin_DZbishe3 天前
基于django在线音乐数据采集的设计与实现-计算机毕设 附源码 22647
javascript·spring boot·mysql·django·node.js·php·html5
longxiangam3 天前
Composer 私有仓库搭建
php·composer
上海云盾-高防顾问4 天前
DNS异常怎么办?快速排查+解决指南
开发语言·php