注解路由 + 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;
相关推荐
笙枫6 小时前
LangGraph Agent 架构基础:从概念到第一个可运行的Agent
开发语言·架构·php
小代码20167 小时前
ubuntu vscode docker php 环境搭建
vscode·ubuntu·docker·php·laravel
Maybe I Simple7 小时前
二进制打包|phar打包
php·webman
旧梦吟8 小时前
脚本网页 嵌入式-笔记模板
stm32·嵌入式硬件·html5
zorro_z8 小时前
ThinkPHP8学习篇(十四):模板
php
JaguarJack9 小时前
如何使用 PHP 的 for、while 和 foreach 循环实现极致性能与零 Bug 代码
后端·php
BingoGo9 小时前
如何使用 PHP 的 for、while 和 foreach 循环实现极致性能与零 Bug 代码
后端·php
lskblog20 小时前
PHP中正确处理HTTP响应:从原始响应到JSON数组的完整指南
http·json·php·laravel
万岳软件开发小城1 天前
2026 在线教育新趋势:网校系统源码正在重塑教育培训平台开发模式
人工智能·php·在线教育系统源码·教育平台搭建·教育app开发·教育软件开发