Day29 Swagger

年轻人不要看到标题就兴奋好吗?

以目前前後端分离的趋势,前端及後端工程师势必会由两个人以上来担任,那後端工程师做出的API要能清楚地表达给前端工程师势必就很重要,Swagger是一套依照档案里特定的注解转化成可互动的RESTful API文件的套件。

下载套件

composer require "darkaonline/l5-swagger"

发布其他资源

php artisan vendor:publish --provider "L5Swagger\L5SwaggerServiceProvider"

虽然该套件会自动搜寻全部档案并找到特定注解来生成文件,也就代表说注解可以写在任何地方,例如Controller、Service、Model层等等地方,但为了方便管理还是为其生成专属资料夹,Swagger的全部设定会放在config的l5-swagger.php里,但今天先全部使用预设值即可

创建文件专属资料夹
Mkdir app/Docs

创建基本档案

touch app/Docs/Info.php
touch app/Docs/Security.php
touch app/Docs/Server.php

填入资料对应资料

Info

<?php
/**
 * @OA\Info(
 *      version="1.0.0",
 *      title="Iron man",
 *      description="",
 *      @OA\Contact(
 *          email="[email protected]"
 *      )
 * )
*/

Security

<?php
/**
 * @OA\SecurityScheme(
 *      securityScheme="Authorization",
 *      in="header",
 *      type="http",
 *      scheme="bearer",
 *      name="Authorization"
 * )
 */

Server

<?php
/**
 * @OA\Server(
 *       url = "http://127.0.0.1:8080",
 *       description="local"   
 * )
 * @OA\Server(
 *       url = "http://xx.xx.xx.xx:80",
 *       description="ec2"   
 * )
*/

先利用Day19的案例来写第一个范例
先开启本机服务
php artisan serve

列表功能
GET method
Url = http://domain:8000/api/messages

建立Message专属档案

touch app/Docs/Message.php

填入对应资料

<?php
/**
 * @OA\Get(
 *      path="/api/messages",
 *      tags={"Message"},
 *      summary="List Message",
 *      security={{"Authorization":{}}},
 *      @OA\Response(
 *          response=200,
 *          description="success",
 *          @OA\MediaType(
 *              mediaType="application\json",
 *              @OA\Schema(
 *                  example={
 *                      {
 *                          "id" : 751,
 *                          "member": "Mr. Keven Quigley",
 *                          "message": "Ipsam hic consectetur consectetur autem ut.",
 *                          "created_at": "2021-09-29T08:41:27.000000Z"
 *                      },
 *                      {
 *                          "id": 753,
 *                          "member": "Miss Jacky Effertz",
 *                          "message": "Amet minima enim mollitia ducimus.",
 *                          "created_at": "2021-09-29T08:41:27.000000Z"
 *                      }
 *                  }
 *              )
 *          )
 *      )
 * )
 */

下指令建立文件

php artisan l5-swagger:generate

生成的档案会在storage/api-docs/api-docs.json
这个档案是不需要被git纪录的
所以在laravel/.gitignore档案里添加/storage/api-docs

此时可以打开浏览器至http://127.0.0.1:8000/api/documentation即可看到文件,如果不想要每次都要手动下指令建立文件的话也可以在.env档的地方添加设定

L5_SWAGGER_GENERATE_ALWAYS=true

如此一来每次文件被开启时套件都会自动编译一次

https://ithelp.ithome.com.tw/upload/images/20210929/20115048OQFjjidY8n.png

左边Servers的地方可以切换环境,例如在Git Flow就会有local、dev、release、master等环境
如果有需要登入验证,例如JWT验证方式等等即可登入一次後将Token填入在右边的Authorize

接着就可以看到利用tags分类的API了,以List Message为例,会直接看到已经先写好的example范例格式,但更方便是的是可以点击右上角的Try it out後点选Execute,套件会模拟前端call API,下方的Response Body变成真实的资料库资料,有时有些环境问题在本机测试时不会有问题,但利用Swagger这种方式会发现一些原本没注意到的Bug,所以在写好文件要交给前端工程师前请自行测试一下API是否能够串接。

https://ithelp.ithome.com.tw/upload/images/20210929/20115048JPbWAnYBKF.png

https://ithelp.ithome.com.tw/upload/images/20210929/20115048Cb3gQtUB8B.png

接着就把全部的CRUD都写完吧,因为是同一系列的功能,都写在Message.php里即可,一样的功能使用一个的tags属性,method、path、summary记得要变更。

create

/**
 * @OA\Post(
 *      path="/api/messages",
 *      tags={"Message"},
 *      summary="Create Message",
 *      security={{"Authorization":{}}},
 *      @OA\RequestBody(
 *          @OA\MediaType(
 *              mediaType="application/json",
 *              @OA\Schema(
 *                  @OA\Property(
 *                      property="member",
 *                      type="string"
 *                  ),
 *                  @OA\Property(
 *                      property="message",
 *                      type="string"
 *                  ),
 *                  example={
 *                      "member" : "kkk",
 *                      "message" : "very good"
 *                  }
 *              )
 *          )
 *      ),
 *      @OA\Response(
 *          response=200,
 *          description="success"
 *      )
 * )
 */

detail

/**
 * @OA\Get(
 *      path="/api/messages/{id}",
 *      tags={"Message"},
 *      summary="Get Message by Id",
 *      security={{"Authorization":{}}},
 *      @OA\Parameter(
 *          name="id",
 *          required=true,
 *          in="path",
 *          @OA\Schema(
 *              type="integer",
 *              example="300"
 *          )
 *      ),
 *      @OA\Response(
 *          response=200,
 *          description="success",
 *          @OA\MediaType(
 *              mediaType="application\json",
 *              @OA\Schema(
 *                  example={
 *                      "id": 764,
 *                      "member": "verycow",
 *                      "message": "first test",
 *                      "created_at": "2021-09-29T14:11:34.000000Z",
 *                      "updated_at": "2021-09-29T14:11:34.000000Z"
 *                  }
 *              )
 *          )
 *      )
 * )
 */

update

/**
 * @OA\Put(
 *      path="/api/messages/{id}",
 *      tags={"Message"},
 *      summary="Update Message",
 *      security={{"Authorization":{}}},
 *      @OA\Parameter(
 *          name="id",
 *          required=true,
 *          in="path",
 *          @OA\Schema(
 *              type="integer",
 *              example="300"
 *          )
 *      ),
 *      @OA\RequestBody(
 *          @OA\MediaType(
 *              mediaType="application/json",
 *              @OA\Schema(
 *                  @OA\Property(
 *                      property="member",
 *                      type="string"
 *                  ),
 *                  @OA\Property(
 *                      property="message",
 *                      type="string"
 *                  ),
 *                  example={
 *                      "member" : "kkk",
 *                      "message" : "very good again"
 *                  }
 *              )
 *          )
 *      ),
 *      @OA\Response(
 *          response=200,
 *          description="success"
 *      )
 * )
 */

delete

/**
 * @OA\Delete(
 *      path="/api/messages/{id}",
 *      tags={"Message"},
 *      summary="Delete Message",
 *      security={{"Authorization":{}}},
 *      @OA\Parameter(
 *          name="id",
 *          required=true,
 *          in="path",
 *          @OA\Schema(
 *              type="integer",
 *              example="300"
 *          )
 *      ),
 *      @OA\Response(
 *          response=200,
 *          description="success"
 *      )
 * )
 */

比较重要的差异是有些资料是带在Url上的,就要使用Parameter的方式来带入,如果是Body里面的就使用RequestBody,虽然使用这个套件会需要非常多的空白键或是tab,但我觉得能把文件整理漂亮让下一位使用者能舒舒服服的继承比较重要

今天的介绍就到这边结束了,谢谢观看的各位,请记得按赞分享开启小铃铛,你的支持会让按赞数+1。


<<:  创建App-(老师版)作业派发

>>:  [Day14] Boxenn 实作 Source Wrapper

【Day5】後端设定(前端的建立在晚一点)

因为某种神秘的原因(公司比较忙),所以目前前端的建立过程可能会明後天才会介绍 1.後端与前端的架构:...

Day26 - 使用 Guard 来实作一个马克杯的状态机

还记得在 Day 15 马克杯 装水 Guard 的例子吗? 另外一组例子,一个水瓶或是马克杯的状态...

强型闯入DenoLand[30] - Web API 实作篇

强型闯入DenoLand[30] - Web API 实作篇 在介绍完 Denon 的使用方法以及...

ASP.NET MVC 从入门到放弃(Day18)-MVC检视(View)介绍

接下来讲讲View 部分... 在控制器的ActionResult Index() 上方可点选右键新...

[Day26] React - 设定属性(style属性 & 事件属性)

设定style属性 上一篇有提到我们可以在React.createElement的第二个参数设定Re...