作爲一名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="[email protected]",
* 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文檔,感興趣的不妨嘗試一下。