ThinkPHP與Gin框架之集成SwaggerApi接口文檔生成工具
大家好,我是碼農(nóng)先森。
想必大家對接口文檔都不陌生了,程序員有件很苦惱的事情就是「最討厭別人的項目不寫接口文檔,但是又最討厭自己來寫文檔」說的是不是你哈哈。雖然很討厭,但是你也沒有辦法啊,畢竟人還得吃飯,又不能提桶跑路。其實寫接口文檔并不全是壞處,好處也是很多的,比如可以減少前后端的扯皮成本、清晰的接口文檔可以讓對方閉嘴、避免大家亂甩鍋等等。
在之前我也不喜歡寫接口文檔,也不喜歡寫注釋,然后過一段時間來看自己的代碼,結(jié)果一臉懵逼自己都看不懂了,我相信大家也這種經(jīng)歷吧,所以嘛有時間還是得寫寫,避免出現(xiàn)自己挖坑自己跳的尷尬局面。那么這次我主要分享的內(nèi)容是 SwaggerApi 接口文檔,不過有人會質(zhì)疑了這個東西不是大家都會用了嗎?但是我想說的是,你會用但是不代表所有人都會哦,所以呢這篇文章主要是分享給那些還未曾使用過這個工具的人,希望對這些人能有所幫助。
話不多說,開整!我們先來看一下整體的項目目錄結(jié)構(gòu),內(nèi)容主要分為 PHP 和 Go 兩部分。
[manongsen@root php_to_go]$ tree -L 2
.
├── go_swagger
│ ├── app
│ │ ├── controller
│ │ │ └── user.go
│ │ └── route.go
│ ├── go.mod
│ ├── go.sum
│ └── main.go
└── php_swagger
│ ├── app
│ │ ├── command
│ │ │ └── Swagger.php
│ │ ├── controller
│ │ │ └── User.php
│ ├── composer.json
│ ├── composer.lock
│ ├── config
│ ├── public
│ │ |── swagger-ui
│ │ └── swagger.json
│ ├── route
│ │ └── app.php
│ ├── think
│ ├── vendor
│ └── .env
ThinkPHP
使用 composer 創(chuàng)建基于 ThinkPHP 框架的 php_swagger 項目。
## 當(dāng)前目錄
[manongsen@root ~]$ pwd
/home/manongsen/workspace/php_to_go/php_swagger
## 安裝 ThinkPHP 框架
[manongsen@root php_swagger]$ composer create-project topthink/think php_swagger
[manongsen@root php_swagger]$ cp .example.env .env
## 安裝 Swagger 相關(guān) Composer 擴展包
[manongsen@root php_swagger]$ composer require zircote/swagger-php
[manongsen@root php_swagger]$ composer require doctrine/annotations
執(zhí)行 php think make:command Swagger 命令,創(chuàng)建一個用于生成 Swagger 文檔的腳本。
<?php
declare (strict_types = 1);
namespace app\command;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
use app;
use OpenApi\Generator;
class Swagger extends Command
{
protected function configure()
{
// 指令配置
$this->setName('app\command\swagger')
->setDescription('the app\command\swagger command');
}
protected function execute(Input $input, Output $output)
{
$openapi = \OpenApi\Generator::scan([__DIR__ . '/../../app/controller/']);
file_put_contents(__DIR__ . '/../../public/swagger.json', $openapi->toJson());
$output->writeln('執(zhí)行成功, 接口文檔請訪問 http://127.0.0.1:8000/swagger-ui/dist/index.html');
// 指令輸出
$output->writeln('app\command\swagger');
}
}
在 php_swagger 項目中執(zhí)行 php think make:Controller User 命令,創(chuàng)建一個 User 控制器。
<?php
namespace app\controller;
use OpenApi\Annotations as OA;
use app\BaseController;
/**
* @OA\Info(title="ThinkPHP框架之用戶中心系統(tǒng) API", version="1.0")
*/
class User extends BaseController
{
/**
* @OA\Get(
* description="用戶詳情",
* path="/api/v1/user/info",
* @OA\Parameter(in="query", required=true, name="user_id", @OA\Schema(type="integer"), description="用戶ID"),
* @OA\Response(
* response=200,
* description="返回數(shù)據(jù)",
* @OA\JsonContent(type="object",
* @OA\Property(property="code", type="int"),
* @OA\Property(property="message", type="string"),
* @OA\Property(property="data", type="object",
* @OA\Property(property="user_id", type="integer"),
* @OA\Property(property="user_name", type="string"),
* @OA\Property(property="mobile", type="string"),
* @OA\Property(property="email", type="string"),
* ),
* ),
* ),
* @OA\Response(response=401, description="Unauthorized"),
* @OA\Response(response=404, description="Not Found"),
* )
*/
public function info()
{
// TODO::自行實現(xiàn)具體的業(yè)務(wù)邏輯
}
/**
* @OA\Get(
* description="用戶列表",
* path="/api/v1/user/list",
* @OA\Parameter(in="query", required=false, name="page_size", @OA\Schema(type="integer"), description="頁碼"),
* @OA\Parameter(in="query", required=false, name="page_limit", @OA\Schema(type="integer"), description="條數(shù)"),
* @OA\Response(
* response=200,
* description="返回數(shù)據(jù)",
* @OA\JsonContent(type="object",
* @OA\Property(property="code", type="int"),
* @OA\Property(property="message", type="string"),
* @OA\Property(property="data", type="array",
* @OA\Items(type="object",
* @OA\Property(property="user_id", type="integer"),
* @OA\Property(property="user_name", type="string"),
* @OA\Property(property="mobile", type="string"),
* @OA\Property(property="email", type="string"),
* ),
* ),
* ),
* ),
* @OA\Response(response=401, description="Unauthorized"),
* @OA\Response(response=404, description="Not Found"),
* )
*/
public function list()
{
// TODO::自行實現(xiàn)具體的業(yè)務(wù)邏輯
}
/**
* @OA\Post(
* description="創(chuàng)建用戶",
* path="/api/v1/user/create",
* @OA\RequestBody(required=true,description="請求數(shù)據(jù)",content={
* @OA\MediaType(mediaType="application/json",
* @OA\Schema(
* @OA\Property(
* property="username",
* type="string",
* description="用戶名"
* ),
* @OA\Property(
* property="phone",
* type="string",
* description="手機號",
* ),
* @OA\Property(
* property="email",
* type="string",
* description="郵箱",
* )
* )
* )
* }),
* @OA\Response(
* response=200,
* description="返回數(shù)據(jù)",
* @OA\JsonContent(type="object",
* @OA\Property(property="code", type="int"),
* @OA\Property(property="message", type="string"),
* ),
* ),
* @OA\Response(response=401, description="Unauthorized"),
* @OA\Response(response=404, description="Not Found"),
* )
* )
*/
public function create()
{
// TODO::自行實現(xiàn)具體的業(yè)務(wù)邏輯
}
/**
* @OA\Post(
* description="更新用戶",
* path="/api/v1/user/update",
* @OA\RequestBody(required=true, description="請求數(shù)據(jù)", content={
* @OA\MediaType(mediaType="application/json",
* @OA\Schema(
* @OA\Property(
* property="user_id",
* type="integer",
* description="用戶ID",
* ),
* @OA\Property(
* property="username",
* type="string",
* description="用戶名"
* ),
* @OA\Property(
* property="phone",
* type="string",
* description="手機號",
* ),
* @OA\Property(
* property="email",
* type="string",
* description="郵箱",
* )
* )
* )
* }),
* @OA\Response(
* response=200,
* description="返回數(shù)據(jù)",
* @OA\JsonContent(type="object",
* @OA\Property(property="code", type="int"),
* @OA\Property(property="message", type="string"),
* ),
* ),
* @OA\Response(response=401, description="Unauthorized"),
* @OA\Response(response=404, description="Not Found"),
* )
* )
*/
public function update()
{
// TODO::自行實現(xiàn)具體的業(yè)務(wù)邏輯
}
}
先執(zhí)行 php think swagger 生成 Swagger 文檔,然后再執(zhí)行 php think run 運行項目,最后在瀏覽器上訪問地址 http://127.0.0.1:8000/swagger-ui/dist/index.html 即可看到實際效果。
圖片
Gin
通過 go mod 初始化 go_swagger 項目。
## 當(dāng)前目錄
[manongsen@root ~]$ pwd
/home/manongsen/workspace/php_to_go/go_swagger
[manongsen@root go_swagger]$ go mod init go_swagger
## 安裝 Gin 框架
[manongsen@root go_swagger]$ go get github.com/gin-gonic/gin
## 安裝 Swagger 相關(guān)依賴庫
[manongsen@root go_swagger]$ go get github.com/swaggo/files
[manongsen@root go_swagger]$ go get github.com/swaggo/gin-swagger
## 安裝 Swagger 文檔生成工具
[manongsen@root go_swagger]$ go install github.com/swaggo/swag/cmd/swag@latest
在 go_swagger 項目中創(chuàng)建 user 控制器。
package controller
import (
"github.com/gin-gonic/gin"
)
type UserStruct struct {
UserId string `json:"user_id"`
UserName string `json:"user_name"`
Mobile string `json:"mobile"`
Email string `json:"email"`
}
type UserInfoRespose struct {
Code int `json:"code" `
Message string `json:"message"`
Data UserStruct `json:"data"`
}
// @BasePath /api/v1
// 用戶信息
// @Summary 用戶信息
// @Schemes
// @Description 用戶信息
// @Tags user
// @Produce json
// @Param id path int true "用戶ID"
// @success 200 {object} UserInfoRespose{data=UserStruct} "返回數(shù)據(jù)"
// @failure 401 string Unauthorized "Unauthorized"
// @failure 404 string NotFound "Not Found"
// @Router /user/info [get]
func UserInfo(c *gin.Context) {
// TODO::自行實現(xiàn)具體的業(yè)務(wù)邏輯
}
type UserListRespose struct {
Code int `json:"code" `
Message string `json:"message"`
Data []*UserStruct `json:"data"`
}
// @BasePath /api/v1
// 用戶列表
// @Summary 用戶列表
// @Schemes
// @Description 用戶列表
// @Tags user
// @Produce json
// @Param page_size path int true "頁碼"
// @Param page_limit path int true "條數(shù)"
// @success 200 {object} UserListRespose{data=[]UserStruct} "返回數(shù)據(jù)"
// @failure 401 string Unauthorized "Unauthorized"
// @failure 404 string NotFound "Not Found"
// @Router /user/list [get]
func UserList(c *gin.Context) {
// TODO::自行實現(xiàn)具體的業(yè)務(wù)邏輯
}
type CreateUserRequest struct {
UserName string `json:"user_name"`
Mobile string `json:"mobile"`
Email string `json:"email"`
}
type CreateUserRespose struct {
Code int `json:"code" `
Message string `json:"message"`
}
// @BasePath /api/v1
// 創(chuàng)建用戶
// @Summary 創(chuàng)建用戶
// @Schemes
// @Description 創(chuàng)建用戶
// @Tags user
// @Accept json
// @Produce json
// @Param req body CreateUserRequest true "創(chuàng)建用戶"
// @success 200 {object} CreateUserRespose{} "返回數(shù)據(jù)"
// @failure 401 string Unauthorized "Unauthorized"
// @failure 404 string NotFound "Not Found"
// @Router /user/create [post]
func CreateUser(c *gin.Context) {
// TODO::自行實現(xiàn)具體的業(yè)務(wù)邏輯
}
type UpdateUserRequest struct {
UserId string `json:"user_id"`
UserName string `json:"user_name"`
Mobile string `json:"mobile"`
Email string `json:"email"`
}
type UpdateUserRespose struct {
Code int `json:"code" `
Message string `json:"message"`
}
// @BasePath /api/v1
// 更新用戶
// @Summary 更新用戶
// @Schemes
// @Description
// @Tags user
// @Accept json
// @Produce json
// @Param req body UpdateUserRequest true "更新用戶"
// @success 200 {object} UpdateUserRespose{} "返回數(shù)據(jù)"
// @failure 401 string Unauthorized "Unauthorized"
// @failure 404 string NotFound "Not Found"
// @Router /user/update [post]
func UpdateUser(c *gin.Context) {
// TODO::自行實現(xiàn)具體的業(yè)務(wù)邏輯
}
先執(zhí)行 swag init 命令生成 Swagger 文檔,然后再執(zhí)行 go run main.go 運行項目,最后在瀏覽器上訪問 http://127.0.0.1:8080/swagger/index.html 即可看到實際效果。
圖片
接口文檔是每個項目都不可或缺的部分,同時也是前后端聯(lián)調(diào)接口的橋梁,它讓團隊的協(xié)作效率得到了顯著的提升。SwaggerApi 接口文檔只需要在相應(yīng)代碼的位置寫上對應(yīng)的注釋,便可以通過工具生成文檔,這種方式極大的簡化了寫接口文檔的工作量。通過這次內(nèi)容的分享相信大家對這個工具都有些許的了解了吧,不過最好是能自己再實踐一遍,學(xué)習(xí)的效果會更好。如果有想要獲取完整的代碼的朋友,可以在公眾號內(nèi)回復(fù)「5148」即可獲取到,希望對大家能有所幫助,此外為了方便大家學(xué)習(xí)再附上相關(guān)的官方文檔。
- https://zircote.github.io/swagger-php/
- https://github.com/swaggo/swag/blob/master/README.md