[TOC]

作为一名phper,在使用Lumen框架开发微服务的时候,API文档的书写总是少不了的,比较流行的方式是使用swagger来写API文档,但是与Java语言原生支持 annotation 不同,php只能单独维护一份swagger文档,或者在注释中添加annotations来实现类似的功能,但是注释中书写Swagger注解是非常痛苦的,没有代码提示,没有格式化。
本文将会告诉你如何借助phpstorm中annotations插件,在开发Lumen微服务项目时(Laravel项目和其它php项目方法类似)快速的在代码中使用注释来创建swagger文档。
本文将会持续修正和更新,最新内容请参考我的 GITHUB 上的 程序猿成长计划 项目,欢迎 Star,更多精彩内容请 follow me。
框架配置
我们使用当前最新的 Lumen 5.7 来演示。演示代码放到了github,感兴趣的可以参考一下
https://github.com/mylxsw/lumen-swagger-demo
安装依赖
在Lumen项目中,首先需要使用 composer 安装SwaggerLume项目依赖
composer require darkaonline/swagger-lume

项目配置
在bootstrap/app.php文件中,去掉下面配置的注释(大约在26行),启用Facades支持。
$app->withFacades();
启用SwaggerLume 项目的配置文件,在 Register Container Bindings部 分前面,添加
$app->configure('swagger-lume');
然后,在 Register Service Providers 部分,注册 SwaggerLume 的ServiceProvider
$app->register(\SwaggerLume\ServiceProvider::class);
在项目的根目录,执行命令 php artisan swagger-lume:publish 发布swagger相关的配置

执行该命令后,主要体现以下几处变更

- 在
config/目录中,添加了项目的配置文件swagger-lume.php - 在
resources/views/vendor目录中,生成了swagger-lume/index.blade.php视图文件,用于预览生成的API文档
从配置文件中我们可以获取以下关键信息
- api.title 生成的API文档显示标题
- routes.api 用于访问生成的API文档UI的路由地址默认为
/api/documentation - routes.docs 用于访问生成的API文档原文,json格式,默认路由地址为
/docs - paths.docs 和 paths.docs_json 组合生成 api-docs.json 文件的地址,默认为
storage/api-docs/api-docs.json,执行php artisan swagger-lume:generate命令时,将会生成该文件
语法自动提示
纯手写swagger注释肯定是要不得的,太容易出错,还需要不停的去翻看文档参考语法,因此我们很有必要安装一款能够自动提示注释中的注解语法的插件,我们常用的IDE是 phpstorm,在 phpstorm 中,需要安装 PHP annotation 插件

安装插件之后,我们在写Swagger文档时,就有代码自动提示功能了

书写文档
Swagger文档中包含了很多与具体API无关的信息,我们在 app/Http/Controllers 中创建一个 SwaggerController,该控制器中我们不实现业务逻辑,只用来放置通用的文档信息
1<?php 2namespace App\Http\Controllers; 3 4use OpenApi\Annotations\Contact; 5use OpenApi\Annotations\Info; 6use OpenApi\Annotations\Property; 7use OpenApi\Annotations\Schema; 8use OpenApi\Annotations\Server; 9 10/** 11 * 12 * @Info( 13 * version="1.0.0", 14 * title="演示服务", 15 * description="这是演示服务,该文档提供了演示swagger api的功能", 16 * @Contact( 17 * email="mylxsw@aicode.cc", 18 * name="mylxsw" 19 * ) 20 * ) 21 * 22 * @Server( 23 * url="http://localhost", 24 * description="开发环境", 25 * ) 26 * 27 * @Schema( 28 * schema="ApiResponse", 29 * type="object", 30 * description="响应实体,响应结果统一使用该结构", 31 * title="响应实体", 32 * @Property( 33 * property="code", 34 * type="string", 35 * description="响应代码" 36 * ), 37 * @Property(property="message", type="string", description="响应结果提示") 38 * ) 39 * 40 * 41 * @package App\Http\Controllers 42 */ 43class SwaggerController 44{}
接下来,在业务逻辑控制器中,我们就可以写API了
1<?php 2namespace App\Http\Controllers; 3 4use App\Http\Responses\DemoAdditionalProperty; 5use App\Http\Responses\DemoResp; 6use Illuminate\Http\Request; 7use OpenApi\Annotations\Get; 8use OpenApi\Annotations\MediaType; 9use OpenApi\Annotations\Property; 10use OpenApi\Annotations\RequestBody; 11use OpenApi\Annotations\Response; 12use OpenApi\Annotations\Schema; 13 14class ExampleController extends Controller 15{ 16 17 /** 18 * @Get( 19 * path="/demo", 20 * tags={"演示"}, 21 * summary="演示API", 22 * @RequestBody( 23 * @MediaType( 24 * mediaType="application/json", 25 * @Schema( 26 * required={"name", "age"}, 27 * @Property(property="name", type="string", description="姓名"), 28 * @Property(property="age", type="integer", description="年龄"), 29 * @Property(property="gender", type="string", description="性别") 30 * ) 31 * ) 32 * ), 33 * @Response( 34 * response="200", 35 * description="正常操作响应", 36 * @MediaType( 37 * mediaType="application/json", 38 * @Schema( 39 * allOf={ 40 * @Schema(ref="#/components/schemas/ApiResponse"), 41 * @Schema( 42 * type="object", 43 * @Property(property="data", ref="#/components/schemas/DemoResp") 44 * ) 45 * } 46 * ) 47 * ) 48 * ) 49 * ) 50 * 51 * @param Request $request 52 * 53 * @return DemoResp 54 */ 55 public function example(Request $request) 56 { 57 // TODO 业务逻辑 58 59 $resp = new DemoResp(); 60 $resp->name = $request->input('name'); 61 $resp->id = 123; 62 $resp->age = $request->input('age'); 63 $resp->gender = $request->input('gender'); 64 65 $prop1 = new DemoAdditionalProperty(); 66 $prop1->key = "foo"; 67 $prop1->value = "bar"; 68 69 $prop2 = new DemoAdditionalProperty(); 70 $prop2->key = "foo2"; 71 $prop2->value = "bar2"; 72 73 $resp->properties = [$prop1, $prop2]; 74 75 return $resp; 76 } 77}
这里,我们在响应结果中,引用了在SwaggerController中定义的 ApiResponse,还引用了一个没有定义的ExampleResp对象,我们可以 app\Http\Responses 目录(自己创建该目录)中实现该ExampleResp对象,我们将响应对象都放在这个目录中
1<?php 2 3namespace App\Http\Responses; 4 5use OpenApi\Annotations\Items; 6use OpenApi\Annotations\Property; 7use OpenApi\Annotations\Schema; 8 9/** 10 * @Schema( 11 * title="demo响应内容", 12 * description="demo响应内容描述" 13 * ) 14 * 15 * @package App\Http\Responses 16 */ 17class DemoResp extends JsonResponse 18{ 19 20 /** 21 * @Property( 22 * type="integer", 23 * description="ID" 24 * ) 25 * 26 * @var int 27 */ 28 public $id = 0; 29 30 /** 31 * @Property( 32 * type="string", 33 * description="用户名" 34 * ) 35 * 36 * @var string 37 */ 38 public $name; 39 40 /** 41 * @Property( 42 * type="integer", 43 * description="年龄" 44 * ) 45 * 46 * @var integer 47 */ 48 public $age; 49 50 /** 51 * @Property( 52 * type="string", 53 * description="性别" 54 * ) 55 * 56 * @var string 57 */ 58 public $gender; 59 60 /** 61 * @Property( 62 * type="array", 63 * @Items(ref="#/components/schemas/DemoAdditionalProperty") 64 * ) 65 * 66 * @var array 67 */ 68 public $properties = []; 69}
返回对象引用其它对象
1<?php 2namespace App\Http\Responses; 3 4use OpenApi\Annotations\Property; 5use OpenApi\Annotations\Schema; 6 7/** 8 * 9 * @Schema( 10 * title="额外属性", 11 * description="额外属性描述" 12 * ) 13 * 14 * @package App\Http\Responses 15 */ 16class DemoAdditionalProperty 17{ 18 /** 19 * @Property( 20 * type="string", 21 * description="KEY" 22 * ) 23 * 24 * @var string 25 */ 26 public $key; 27 28 /** 29 * @Property( 30 * type="string", 31 * description="VALUE" 32 * ) 33 * 34 * @var string 35 */ 36 public $value; 37}
生成文档
执行下面的命令,就可以生成文档了,生成的文档在storage/api-docs/api-docs.json。
php artisan swagger-lume:generate
预览文档
打开浏览器访问 http://访问地址/docs,可以看到如下内容

访问 http://访问地址/api/documentation,我们看到

接口详细信息展开

更多
本文简述了如何在Lumen项目中使用代码注释自动生成Swagger文档,并配合phpstorm的代码提示功能,然而,学会了这些还远远不够,你还需要去了解Swagger文档的语法结构,在 swagger-php 项目的 Examples 目录中包含很多使用范例,你可以参考一下。
团队项目中使用了swagger文档,但是总得有个地方管理文档吧,这里推荐一下 Wizard 项目,该项目是一款用于团队协作的文档管理工具,支持Markdown文档和Swagger文档,感兴趣的不妨尝试一下。