从零开始系列-Laravel编写api服务接口:12.编写swagger3.0 API文档

Laravel框架
494
0
0
2022-04-12
标签   Swagger

简介

api文档是个比较重要的话题,每个团队都有自己的api习惯,比如我们目前用的apizza来管理接口,也可以用postman。但是不管用什么感觉前端对后端的接口都不是很满意:)(手动狗头),这个问题不过多讨论,下面介绍一种比较强大的swagger,集成到laravel中的一些用法。

swagger集成分为swagger-php 和 swagger-ui,可以分别安装,swagger-php用来编写文档的注解,生成json或其它格式的注解,swagger-ui是一个前端项目,负责将json导入到项目,以便直接访问调试。

文档地址(包括安装方法和版本对比)

github.com/DarkaOnLine/L5-Swagger/...

附录 swagger-php2和swagger-php3.0的比较文档 zircote.github.io/swagger-php/Migr...
无非就是移除了一些属性,修改了一些属性,将@SWG改为了@OA

根据本文章案例用的是laravel 8.0,所以需要用最新版的swagger3.0,安装方法如下:

1.安装

composer require "darkaonline/l5-swagger"

php artisan vendor:publish --provider "L5Swagger\L5SwaggerServiceProvider"
## 先把配置文件加上.env 最后加上L5_SWAGGER_CONST_HOST = http://homestead.test/

打开config/l5-swagger.php 配置文件

'constants' => ['L5_SWAGGER_CONST_HOST' => env('L5_SWAGGER_CONST_HOST', 'http://my-default-host.com'),],

php artisan l5-swagger:generate // 此命令是重置swagger的json,每次编写都要重新运行一下,如果想要自动生成也可以

2.app\Http\Controllers\Controller.php 下加上swagger注释

(这是官方文档的注释github.com/DarkaOnLine/L5-Swagger/...)

/**
 * @OA\Info(
 *      version="1.0.0",
 *      title="L5 OpenApi",
 *      description="L5 Swagger OpenApi description",
 *      @OA\Contact(
 *          email="darius@matulionis.lt"
 *      ),
 *     @OA\License(
 *         name="Apache 2.0",
 *         url="http://www.apache.org/licenses/LICENSE-2.0.html"
 *     )
 * )
 */

/**
 * @OA\Server(
 *      url=L5_SWAGGER_CONST_HOST,
 *      description="L5 Swagger OpenApi dynamic host server"
 *  )
 *
 * @OA\Server(
 *      url="https://projects.dev/api/v1",
 *      description="L5 Swagger OpenApi Server"
 * )
 */

/**
 * @OA\SecurityScheme(
 *     type="oauth2",
 *     description="Use a global client_id / client_secret and your username / password combo to obtain a token",
 *     name="Password Based",
 *     in="header",
 *     scheme="https",
 *     securityScheme="Password Based",
 *     @OA\Flow(
 *         flow="password",
 *         authorizationUrl="/oauth/authorize",
 *         tokenUrl="/oauth/token",
 *         refreshUrl="/oauth/token/refresh",
 *         scopes={}
 *     )
 * )
 */

/**
 * @OA\OpenApi(
 *   security={
 *     {
 *       "oauth2": {"read:oauth2"},
 *     }
 *   }
 * )
 */

/**
 * @OA\Tag(
 *     name="project",
 *     description="Everything about your Projects",
 *     @OA\ExternalDocumentation(
 *         description="Find out more",
 *         url="http://swagger.io"
 *     )
 * )
 *
 * @OA\Tag(
 *     name="user",
 *     description="Operations about user",
 *     @OA\ExternalDocumentation(
 *         description="Find out more about",
 *         url="http://swagger.io"
 *     )
 * )
 * @OA\ExternalDocumentation(
 *     description="Find out more about Swagger",
 *     url="http://swagger.io"
 * )
 */

/**
 * @OA\Get(
 *      path="/projects",
 *      operationId="getProjectsList",
 *      tags={"Projects"},
 *      summary="Get list of projects",
 *      description="Returns list of projects",
 *      @OA\Response(
 *          response=200,
 *          description="successful operation"
 *       ),
 *       @OA\Response(response=400, description="Bad request"),
 *       security={
 *           {"api_key_security_example": {}}
 *       }
 *     )
 *
 * Returns list of projects
 */

/**
 * @OA\Get(
 *      path="/projects/{id}",
 *      operationId="getProjectById",
 *      tags={"Projects"},
 *      summary="Get project information",
 *      description="Returns project data",
 *      @OA\Parameter(
 *          name="id",
 *          description="Project id",
 *          required=true,
 *          in="path",
 *          @OA\Schema(
 *              type="integer"
 *          )
 *      ),
 *      @OA\Response(
 *          response=200,
 *          description="successful operation"
 *       ),
 *      @OA\Response(response=400, description="Bad request"),
 *      @OA\Response(response=404, description="Resource Not Found"),
 *      security={
 *         {
 *             "oauth2_security_example": {"write:projects", "read:projects"}
 *         }
 *     },
 * )
 */

直接访问文档就可以了,例如:

homestead.test/api/documentation

附录:以下是我整理的文档结构:

定义公共的返回值并添加引用

注意:During processing the @OA\JsonContent unfolds to @OA\MediaType( mediaType=”application/json”, @OA\Schema( and will generate the same output.

这段话是文档上写的,大家可以试试,我这里就不试了

/**
 * @OA\Get(
 *      path="/projects/{id}",
 *      operationId="getProjectById",
 *      tags={"Projects"},
 *      summary="Get project information",
 *      description="Returns project data",
 *      @OA\Parameter(
 *          name="id",
 *          description="Project id",
 *          required=true,
 *          in="path",
 *          @OA\Schema(
 *              type="integer"
 *          )
 *      ),
 *      @OA\Response(
 *          response=200,
 *          description="successful operation",
 *          @OA\MediaType(
 *         mediaType="application/json",
 *         @OA\Schema(ref="#/components/schemas/DoctorDuty"),
 *     )
 *       ),

 *      @OA\Response(response=400, description="Bad request"),
 *      @OA\Response(response=404, description="Resource Not Found"),
 *      security={
 *         {
 *             "oauth2_security_example": {"write:projects", "read:projects"}
 *         }
 *     },
 * )
 *
 *
 * @OA\Schema(
 *     schema="DoctorDuty",
 *     type="object",
 *     required={""},
 *     example={
"data": {
{
"id": 1,
"week_name": "周一",
"created_at": null,
"updated_at": null,
"days": {
{
"id": 1,
"work_period": "上午8~12点",
"parent_id": 1,
"type": 1,
"created_at": null,
"updated_at": null
}}}}},
 *     @OA\Property(property="id",type="integer",example="1",description="自增id"),
 *     @OA\Property(property="week_name",type="integer",example="周一",description="药店id"),
 *     @OA\Property(property="days",type="array",example="",description="每周下面的具体排期",
 *     @OA\Items(
 *     @OA\Property(property="type",type="integer",example="1",description="1表示工作时间2表示下班时间3表示任何时间"),
 *     @OA\Property(property="work_period",type="integer",example="1",description="描述上下班时间"),
 *     @OA\Property(property="parent_id",type="integer",example="1",description="周id"),
 *     @OA\Property(property="created_at",type="string",example="2020-01-15 13:22:57",description="添加时间"),
 *     @OA\Property(property="updated_at",type="string",example="2020-01-15 13:22:57",description="更新时间"),
 *       )),
 *     @OA\Property(property="created_at",type="string",example="2020-01-15 13:22:57",description="添加时间"),
 *     @OA\Property(property="updated_at",type="string",example="2020-01-15 13:22:57",description="更新时间")
 * )
 */

上面列举了怎么采用引用的方法避免重复代码,如果不需要可以直接写在代码里面去掉ref

关于这部分的文档:


zircote.github.io/swagger-php/Gett...

下面是直接写:

/**
 * @OA\Get(
 *      path="/projects",
 *      operationId="getProjectsList",
 *      tags={"Projects"},
 *      summary="这是project简介",
 *      description="这是project描述",
 *      @OA\Response(response=200, description="successful operation",
 *     @OA\MediaType(
 *         mediaType="application/json",
         * @OA\Schema(
         *     schema="DoctorDuty",
         *     type="object",
         *     required={""},
         *     example={
                "data": {
                    {
                    "id": 1,
                    "week_name": "周一",
                    "created_at": null,
                    "updated_at": null,
                    "days": {
                    {
                    "id": 1,
                    "work_period": "上午8~12点",
                    "parent_id": 1,
                    "type": 1,
                    "created_at": null,
                    "updated_at": null
                    }
                }
        }}},
 *     @OA\Property(property="id",type="integer",example="1",description="自增id"),
 *     @OA\Property(property="week_name",type="integer",example="周一",description="药店id"),
 *     @OA\Property(property="days",type="array",example="",description="每周下面的具体排期",
 *     @OA\Items(
 *     @OA\Property(property="type",type="integer",example="1",description="1表示工作时间2表示下班时间3表示任何时间"),
 *     @OA\Property(property="work_period",type="integer",example="1",description="描述上下班时间"),
 *     @OA\Property(property="parent_id",type="integer",example="1",description="周id"),
 *     @OA\Property(property="created_at",type="string",example="2020-01-15 13:22:57",description="添加时间"),
 *     @OA\Property(property="updated_at",type="string",example="2020-01-15 13:22:57",description="更新时间"),
 *       )),
 *     @OA\Property(property="created_at",type="string",example="2020-01-15 13:22:57",description="添加时间"),
 *     @OA\Property(property="updated_at",type="string",example="2020-01-15 13:22:57",description="更新时间")
 * )),
 *       @OA\Response(response=400, description="Bad request"),
 *     ),
 *       security={
 *           {"api_key_security_example": {}}
 *       },
 *     )
 *
 * Returns list of projects
 */

有童鞋问了老湿能不能再给力一点?

下面介绍如何定义通用parameter

// 定义公共参数医生端token并给出默认值
/**
 * @OA\Parameter(
 *     parameter="DoctorToken",
 *     description="医生token",
 *     name="Authorization",
       @OA\Schema(
 *      type="string",
 *      default="Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8veXhob3NwaXRhbC5sb2NhbC9hcGkvbG9naW4iLCJpYXQiOjE1ODQ1MDA0NDQsImV4cCI6MTU5MjI3NjQ0NCwibmJmIjoxNTg0NTAwNDQ0LCJqdGkiOiJQYmtFWW5PR0NnUnVYZ1ZoIiwic3ViIjo4LCJwcnYiOiJlMTQ3ODdhYWI2NjY4OGNlMDZjNDcxMmU2NzNlMWExYzQ0ZjQ5MDk0IiwiZ3VhcmRfdHlwZSI6ImRvY3RvciJ9.iV8gItmly1yBspgkuQ-Z8KPuHXiw1PgehnJgce3xDHc",
 *      ),
 *      in="header",
 *      required=true,
 *      style = "simple",
 *  )
 */

 // 引用公共参数 文档:https://zircote.github.io/swagger-php/Migrating-to-v3.html#rename-parameter-references/**
 *@OA\Parameter(ref="#/components/parameters/DoctorToken"),
 */

有童鞋问了,Property如果有重复的需要引入怎么办,下面介绍怎么定义一个property并且引入ref

上面介绍了如何引用公共返回值responseparameter 下面介绍怎么定义公共property

// 定义一个property
/**
 * The product name
 * @var string
 *
 * @OA\Schema(
 *   schema="name",
 *   type="string",
 *   description="这是一个名字",
 *   example="王二小",
 * )
 */

// 下面是引用 这样做是为啥呢,官网给的是DRY 文档:https://zircote.github.io/swagger-php/Getting-started.html#reusing-annotations-ref
/**
...
@OA\Property(ref="#/components/schemas/name",property="name"),
...
/*


老湿:能不能再给力点:

// allOf将模型定义组合到新的模式组合中,可以用这种方法处理分页,因为所有的分页都是一样的
/**
 * @OA\Schema(
 *   schema="UpdateItem",
 *   allOf={
 *     @OA\Schema(ref="#/components/schemas/DoctorDuty"),
 *     @OA\Schema(
 *       @OA\Property(property="idaaa", type="integer"),
 *       @OA\Property(property="namebbb", ref="#/components/schemas/name")
 *     )
 *   }
 * )
 */


更多内容请根据文档学习,其实到这里我已经凌乱了~~~ 到此本文章已经完成(是不是非常简单?)