作為一名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
,該控制器中我們不實現業務邏輯,只用來放置通用的文件資訊
<?php
namespace App\Http\Controllers;
use OpenApi\Annotations\Contact;
use OpenApi\Annotations\Info;
use OpenApi\Annotations\Property;
use OpenApi\Annotations\Schema;
use OpenApi\Annotations\Server;
/**
*
* @Info(
* version="1.0.0",
* title="演示服務",
* description="這是演示服務,該文件提供了演示swagger api的功能",
* @Contact(
* email="mylxsw@aicode.cc",
* name="mylxsw"
* )
* )
*
* @Server(
* url="http://localhost",
* description="開發環境",
* )
*
* @Schema(
* schema="ApiResponse",
* type="object",
* description="響應實體,響應結果統一使用該結構",
* title="響應實體",
* @Property(
* property="code",
* type="string",
* description="響應程式碼"
* ),
* @Property(property="message", type="string", description="響應結果提示")
* )
*
*
* @package App\Http\Controllers
*/
class SwaggerController
{}
接下來,在業務邏輯控制器中,我們就可以寫API了
<?php
namespace App\Http\Controllers;
use App\Http\Responses\DemoAdditionalProperty;
use App\Http\Responses\DemoResp;
use Illuminate\Http\Request;
use OpenApi\Annotations\Get;
use OpenApi\Annotations\MediaType;
use OpenApi\Annotations\Property;
use OpenApi\Annotations\RequestBody;
use OpenApi\Annotations\Response;
use OpenApi\Annotations\Schema;
class ExampleController extends Controller
{
/**
* @Get(
* path="/demo",
* tags={"演示"},
* summary="演示API",
* @RequestBody(
* @MediaType(
* mediaType="application/json",
* @Schema(
* required={"name", "age"},
* @Property(property="name", type="string", description="姓名"),
* @Property(property="age", type="integer", description="年齡"),
* @Property(property="gender", type="string", description="性別")
* )
* )
* ),
* @Response(
* response="200",
* description="正常操作響應",
* @MediaType(
* mediaType="application/json",
* @Schema(
* allOf={
* @Schema(ref="#/components/schemas/ApiResponse"),
* @Schema(
* type="object",
* @Property(property="data", ref="#/components/schemas/DemoResp")
* )
* }
* )
* )
* )
* )
*
* @param Request $request
*
* @return DemoResp
*/
public function example(Request $request)
{
// TODO 業務邏輯
$resp = new DemoResp();
$resp->name = $request->input('name');
$resp->id = 123;
$resp->age = $request->input('age');
$resp->gender = $request->input('gender');
$prop1 = new DemoAdditionalProperty();
$prop1->key = "foo";
$prop1->value = "bar";
$prop2 = new DemoAdditionalProperty();
$prop2->key = "foo2";
$prop2->value = "bar2";
$resp->properties = [$prop1, $prop2];
return $resp;
}
}
這裡,我們在響應結果中,引用了在SwaggerController中定義的 ApiResponse
,還引用了一個沒有定義的ExampleResp
物件,我們可以 app\Http\Responses
目錄(自己建立該目錄)中實現該ExampleResp物件,我們將響應物件都放在這個目錄中
<?php
namespace App\Http\Responses;
use OpenApi\Annotations\Items;
use OpenApi\Annotations\Property;
use OpenApi\Annotations\Schema;
/**
* @Schema(
* title="demo響應內容",
* description="demo響應內容描述"
* )
*
* @package App\Http\Responses
*/
class DemoResp extends JsonResponse
{
/**
* @Property(
* type="integer",
* description="ID"
* )
*
* @var int
*/
public $id = 0;
/**
* @Property(
* type="string",
* description="使用者名稱"
* )
*
* @var string
*/
public $name;
/**
* @Property(
* type="integer",
* description="年齡"
* )
*
* @var integer
*/
public $age;
/**
* @Property(
* type="string",
* description="性別"
* )
*
* @var string
*/
public $gender;
/**
* @Property(
* type="array",
* @Items(ref="#/components/schemas/DemoAdditionalProperty")
* )
*
* @var array
*/
public $properties = [];
}
返回物件引用其它物件
<?php
namespace App\Http\Responses;
use OpenApi\Annotations\Property;
use OpenApi\Annotations\Schema;
/**
*
* @Schema(
* title="額外屬性",
* description="額外屬性描述"
* )
*
* @package App\Http\Responses
*/
class DemoAdditionalProperty
{
/**
* @Property(
* type="string",
* description="KEY"
* )
*
* @var string
*/
public $key;
/**
* @Property(
* type="string",
* description="VALUE"
* )
*
* @var string
*/
public $value;
}
生成文件
執行下面的命令,就可以生成文件了,生成的文件在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文件,感興趣的不妨嘗試一下。