Laravel 8 開發中使用 swagger-php 3 生成文件

喝卵形發表於2021-09-10

最近在新專案開發的過程中我發現 swagger-php 升級了版本,而且和以前的文件註釋寫法有了蠻多的差別。官方文件也寫的不是很詳細,在這裡我將結合自己封裝的案例將 Swagger-PHP v3.x 的一些用法分享給大家。

介紹

Laravel 8 開發中使用 swagger-php 3 生成文件

  • 文件生成後效果

Laravel 8 開發中使用 swagger-php 3 生成文件

安裝

  • composer require darkaonline/l5-swagger
  • php artisan vendor:publish --provider "L5Swagger\L5SwaggerServiceProvider"
  • composer require laravel/sanctum

Swagger 可複用的公用引數

  • 我會把文件的一些公共引數( 如 @OA\OpenApi , @OA\OpenApi, @OA\SecurityScheme)寫到 ApiController 裡面。程式碼如下
<?php
namespace App\Apis\V1\Base\Http\Controllers;

use App\Http\Controllers\Controller;

abstract class ApiController extends Controller
{
    /**
     * @OA\OpenApi(
     *   @OA\Server(
     *      url="/api/v1"
     *   ),
     *   @OA\Info(
     *      title="Swagger-Demo",
     *      version="1.0.0",
     *   ),
     * )
     */



    /**
     *@OA\Tag(name="UnAuthorize", description="No user login required")
     */

    /**
     *@OA\Tag(name="Authorize", description="User login required")
     */


    /**
     * @OA\SecurityScheme(
     *       scheme="Bearer",
     *       securityScheme="Bearer",
     *       type="apiKey",
     *       in="header",
     *       name="Authorization",
     * )
     */
}
  • 圖片對應

Laravel 8 開發中使用 swagger-php 3 生成文件

Swagger 請求引數

POST 請求

swagger-php 3.* 以前我們如果 Post 請求引數很多,那麼在控制器我們可能寫很多的註釋。導致程式碼特別冗餘。 swagger-php 3.* 我是通過 表單驗證 來解決這個問題的。同時程式碼也更清晰規範。

<?php

namespace App\Apis\V1\Users\Http\Controllers;

use App\Apis\V1\Base\Http\Controllers\ApiController;
use App\Apis\V1\Users\Http\Requests\RegisterRequest;
use App\Models\User;
use Illuminate\Auth\Events\Registered;
use Illuminate\Support\Facades\Hash;

class RegisterController extends ApiController
{
    /**
     * @OA\Post  (
     *     tags={"UnAuthorize"},
     *     path="/user/register",
     *     summary="user register",
     *     @OA\RequestBody(
     *         @OA\MediaType(
     *             mediaType="application/x-www-form-urlencoded",
     *             @OA\Schema(
     *                 type="object",
     *                 ref="#/components/schemas/RegisterRequest",
     *             )
     *         )
     *     ),
     *     @OA\Response(response="401", description="fail", @OA\JsonContent(ref="#/components/schemas/ApiRequestException")),
     *     @OA\Response(response="200", description="An example resource", @OA\JsonContent(type="object", @OA\Property(format="string", default="20d338931e8d6bd9466edeba78ea7dce7c7bc01aa5cc5b4735691c50a2fe3228", description="token", property="token"))),
     * )
     */
    public function register(RegisterRequest $request)
    {
        $params = $request->validated();

        $user = User::query()->create([
            'name' => $params['name'],
            'email' => $params['email'],
            'password' => Hash::make($params['password']),
        ]);
        event(new Registered($user));

        return response(["token" => $user->createToken($params['email'])->plainTextToken]);
    }
}

在上面程式碼中,我們看不到任何需要請求的引數,@OA\RequestBody 通過 ref 關聯到 #/components/schemas/RegisterRequest,而我們剛好有個表單請求類 RegisterRequest。在 swagger-php 3.* 我們可以把文件 post 引數的註釋放到表單請求類 RegisterRequestRegisterRequest 程式碼如下:

<?php
namespace App\Apis\V1\Users\Http\Requests;

use App\Apis\V1\Base\Http\Requests\Request;

/**
 * @OA\Schema()
 */
class RegisterRequest extends Request
{

    /**
     * @OA\Property(format="string", default="xingxiang", description="name", property="name"),
     * @OA\Property(format="string", default="xingxiang@spacebib.com", description="email", property="email"),
     * @OA\Property(format="string", default="password", description="password", property="password"),
     * @OA\Property(format="string", default="password", description="password confirmation", property="password confirmation"),
     */
    public function rules()
    {
        return [
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
            'password' => ['required', 'string', 'min:8', 'confirmed'],
        ];
    }
}
  • 生成文件效果

Laravel 8 開發中使用 swagger-php 3 生成文件

GET 請求

我們以獲取使用者列表和獲取使用者詳情,分別演示路由引數和請求引數註釋如何編寫。

/**
     * @OA\Get(
     *     tags={"Authorize"},
     *     path="/users/{id}",
     *     summary="get user detail",
     *     security={{ "Bearer":{} }},
     *     @OA\Parameter(
     *        name="id",
     *        in="path",
     *        description="user Id",
     *        @OA\Schema(
     *           type="integer",
     *           format="int64"
     *        ),
     *        required=true,
     *        example=1
     *     ),
     *     @OA\Response(response="401", description="fail", @OA\JsonContent(ref="#/components/schemas/ApiRequestException")),
     *     @OA\Response(response="404", description="fail", @OA\JsonContent(ref="#/components/schemas/ApiNotFoundException")),
     *     @OA\Response(response="200", description="success",@OA\JsonContent(ref="#/components/schemas/UserResource")))
     * )
     * @param  int  $id
     * @return UserResource
     */
    public function show(int $id)
    {
        try {
            return new UserResource(User::query()->findOrFail($id));
        } catch (\Exception $exception) {
            throw new ApiNotFoundException();
        }
    }

Laravel 8 開發中使用 swagger-php 3 生成文件

/**
     * @OA\Get(
     *     tags={"Authorize"},
     *     path="/users",
     *     summary="get user list",
     *     security={{ "Bearer":{} }},
     *     @OA\Parameter(
     *         name="offset",
     *         @OA\Schema(
     *             type="integer",
     *             format="int64"
     *         ),
     *         in="query",
     *         description="offset",
     *         example=0,
     *         required=true,
     *     ),
     *     @OA\Parameter(
     *         name="limit",
     *         @OA\Schema(
     *             type="integer",
     *             format="int64"
     *         ),
     *         in="query",
     *         description="offset",
     *         example=10,
     *         required=true,
     *     ),
     *     @OA\Response(response="401", description="fail", @OA\JsonContent(ref="#/components/schemas/ApiRequestException")),
     *     @OA\Response(response="200", description="success",@OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/UserResource"))))
     * )
     * @param  UsersRequest  $request
     * @param  UserRepository  $repository
     * @return AnonymousResourceCollection
     */
    public function index(
        UsersRequest $request,
        UserRepository $repository
    ):AnonymousResourceCollection {
        $offset = $request->get('offset', 0);
        $limit = $request->get('limit', 10);
        return UserResource::collection($repository->get($offset, $limit));
    }

Laravel 8 開發中使用 swagger-php 3 生成文件

Swagger 返回引數

在 Api 返回的時候,有可能是列表,有可能是物件。如果物件引數特別多,按以前我們可能在控制器寫很多註釋文件,導致程式碼很難看,我在專案開發中是將返回的註釋寫到 API 資源 來解決這個問題。

返回陣列列表

Laravel 8 開發中使用 swagger-php 3 生成文件

UserResource 程式碼

<?php
namespace App\Apis\V1\Users\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

/**
 * Class UserResource
 * @package App\Apis\V1\Users\Http\Resources
 * @OA\Schema(
 * )
 */
class UserResource extends JsonResource
{
    /**
     * @OA\Property(format="int64", title="ID", default=1, description="ID", property="id"),
     * @OA\Property(format="string", title="name", default="xingxiang", description="name", property="name"),
     * @OA\Property(format="string", title="email", default="xingxiang@test.com", description="email", property="email")
     */
    public function toArray($request)
    {
        return [
            "id" => $this->id,
            'name' => $this->name,
            'email' => $this->email,
        ];
    }
}

效果

Laravel 8 開發中使用 swagger-php 3 生成文件

返回物件

Laravel 8 開發中使用 swagger-php 3 生成文件

Laravel 8 開發中使用 swagger-php 3 生成文件

從上面我們可以發現 UserResource 是可以複用的,當 @OA\JsonContent(ref="#/components/schemas/UserResource") 裡面有 type = array 返回的就是列表,不然就是物件。

異常返回

Laravel 8 開發中使用 swagger-php 3 生成文件

Laravel 8 開發中使用 swagger-php 3 生成文件

  • ApiNotFoundException 程式碼
<?php
namespace App\Apis\V1\Exceptions;

use Symfony\Component\HttpFoundation\Response;

/**
 * @OA\Schema()
 */
class ApiNotFoundException extends ApiException
{
    /**
     * The err message
     * @var string
     *
     * @OA\Property(
     *   property="message",
     *   type="string",
     *   example="Not Found"
     * )
     */
    public function __construct(string $message = null)
    {
        parent::__construct(self::NO_FOUND_ERROR, $message ?? Response::$statusTexts[self::NO_FOUND_ERROR]);
    }
}

總結

我是通過 API 資源表單驗證 去拆解註釋,同時達到 API 開發目錄的規範。在我專案實際開發中,自己也基於這套規範收益良多。

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章