從零開始系列-Laravel編寫api服務介面:12.編寫swagger3.0 API文件

lixueyuan發表於2021-05-12

簡介

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")
 *     )
 *   }
 * )
 */


更多內容請根據文件學習,其實到這裡我已經凌亂了~~~ 到此本文章已經完成(是不是非常簡單?)

本作品採用《CC 協議》,轉載必須註明作者和本文連結
程式設計兩年半,喜歡ctrl(唱、跳、rap、籃球)

相關文章