一个自动生成API文档的laravel扩展包
手把手教你从零开始写一个laravel扩展包,并发布到packagist,为世界的开源世界做出你自己的贡献
创建基本的目录及结构
- 创建一个laravel项目
- 在项目的根目录创建一个目录packages用于存储测试的扩展包,目录结果如下
packages
├── hanyun
│ └── swagger
│ └── src
复制代码
- 创建Commands目录用于生成console命令
- 创建Controllers目录用于存储控制器
- 创建config目录用于存储配置文件
- 创建routes目录 用于存放我们的路由
- 创建swagger-ui目录用于存放swagger的静态页面
- 创建view目录用于存放显示UI的界面
引入swagger-ui
从swagger官网下载依赖文件,将disk下的文件拷贝到 packages/hanyun/swagger/src/swagger-ui/dist
下面
│ ├── swagger-ui
│ │ └── dist
│ │ ├── favicon-16x16.png
│ │ ├── favicon-32x32.png
│ │ ├── index.html
│ │ ├── oauth2-redirect.html
│ │ ├── swagger-ui-bundle.js
│ │ ├── swagger-ui-bundle.js.map
│ │ ├── swagger-ui-es-bundle-core.js
│ │ ├── swagger-ui-es-bundle-core.js.map
│ │ ├── swagger-ui-es-bundle.js
│ │ ├── swagger-ui-es-bundle.js.map
│ │ ├── swagger-ui-standalone-preset.js
│ │ ├── swagger-ui-standalone-preset.js.map
│ │ ├── swagger-ui.css
│ │ ├── swagger-ui.css.map
│ │ ├── swagger-ui.js
│ │ └── swagger-ui.js.map
复制代码
创建swagger的配置文件,
代码语言:javascript复制文件位置
/packages/hanyun/swagger/src/config/swagger.php
<?php
/**
* User=> Only
* Time=> 16=>30
*/
return [
"info" => [
"title" => "laravel swagger",
"description" => 'laravel swagger generate OpenApi',
"termsOfService" => "http://swagger.io/terms/",
"contact" => [
"email" => "1355081829@qq.com"
],
"license" => [
"name" => "MIT",
"url" => ""
],
"version" => "1.0.0"
],
"servers" => [
[
"url" => "/",
"description" => "laravel swagger OpenApi host"
]
],
];
复制代码
创建视图
代码语言:javascript复制文件位置
packages/hanyun/swagger/src/view/index.blade.php
后面会把这个文件发布到laravel的view目录下面
<!-- HTML for static distribution bundle build -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Swagger UI</title>
<link rel="stylesheet" type="text/css" href="{{asset('swagger-ui/swagger-ui.css')}}" >
<link rel="icon" type="image/png" href="{{asset('swagger-ui/favicon-32x32.png')}}" sizes="32x32" />
<link rel="icon" type="image/png" href="{{asset('swagger-ui/favicon-16x16.png')}}" sizes="16x16" />
<style>
html
{
box-sizing: border-box;
overflow: -moz-scrollbars-vertical;
overflow-y: scroll;
}
*,
*:before,
*:after
{
box-sizing: inherit;
}
body
{
margin:0;
background: #fafafa;
}
</style>
</head>
<body>
<div id="swagger-ui"></div>
<script src="{{asset('swagger-ui/swagger-ui-bundle.js')}}" charset="UTF-8"> </script>
<script src="{{asset('swagger-ui/swagger-ui-standalone-preset.js')}}" charset="UTF-8"> </script>
<script>
window.onload = function() {
// Begin Swagger UI call region
const ui = SwaggerUIBundle({
url: "{{asset('swagger-ui/swagger.json')}}",
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
})
// End Swagger UI call region
window.ui = ui
}
</script>
</body>
</html>
复制代码
创建控制器,用于显示文档界面
代码语言:javascript复制文件位置
packages/hanyun/swagger/src/Controllers/SwaggerController.php
<?php
namespace HanyunSwaggerControllers;
use AppHttpControllersController;
use IlluminateHttpRequest;
class SwaggerController extends Controller
{
//
public function index()
{
return view('swagger-ui.index');
}
}
复制代码
创建路由
代码语言:javascript复制文件位置
packages/hanyun/swagger/src/routes/swagger.php
<?php
/**
* User: Only
* Time: 17:04
*/
use IlluminateSupportFacadesRoute;
Route::get('/swagger', [HanyunSwaggerControllersSwaggerController::class, 'index']);
复制代码
创建console命令用于生成文档
代码语言:javascript复制文件位置
packages/hanyun/swagger/src/Commands/Swagger.php
<?php
namespace AppConsoleCommands;
use IlluminateConsoleCommand;
class Swagger extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'swagger:generate';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Generate swagger API';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$openapi = OpenApiscan(app_path() . '/Http/Controllers');
header('Content-Type: application/json');
$json = $openapi->toJson();
$json = preg_replace('/s{0,}*s{0,}#s{0,}/', '# ', $json);
$json = preg_replace('/s{0,}\\r\\ns{0,}/', 'n', $json);
$json = preg_replace('/s{0,}*s{0,}/', '', $json);
$arr = json_decode($json, true);
$arr['info'] = config('swagger.info');
$arr['servers'] = config('swagger.servers');
$json = json_encode($arr);
file_put_contents(public_path('swagger-ui/swagger.json'), $json);
return 0;
}
}
复制代码
创建门面
代码语言:javascript复制文件位置
packages/hanyun/swagger/src/Facades/Swagger.php
<?php
/**
* User: Only
* Time: 16:39
*/
namespace HanyunSwaggerFacades;
use IlluminateSupportFacadesFacade;
class Swagger extends Facade
{
protected static function getFacadeAccessor()
{
return 'swagger';
}
}
复制代码
创建provider用于发布扩展
代码语言:javascript复制文件位置
packages/hanyun/swagger/src/SwaggerProvider.php
<?php
namespace AppConsoleCommands;
use IlluminateConsoleCommand;
class Swagger extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'swagger:generate';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Generate swagger API';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$openapi = OpenApiscan(app_path() . '/Http/Controllers');
header('Content-Type: application/json');
$json = $openapi->toJson();
$json = preg_replace('/s{0,}*s{0,}#s{0,}/', '# ', $json);
$json = preg_replace('/s{0,}\\r\\ns{0,}/', 'n', $json);
$json = preg_replace('/s{0,}*s{0,}/', '', $json);
$arr = json_decode($json, true);
$arr['info'] = config('swagger.info');
$arr['servers'] = config('swagger.servers');
$json = json_encode($arr);
file_put_contents(public_path('swagger-ui/swagger.json'), $json);
return 0;
}
}
复制代码
修改我们创建的扩展包下面的 composer.json
代码语言:javascript复制
{
"name": "hanyun/swagger",
"description": "Swagger for laravel",
"keywords": [
"swagger",
"laravel",
"openapi"
],
"license": "MIT",
"authors": [
{
"name": "hanyun",
"email": "1355081829@qq.com"
}
],
"autoload": {
"psr-4": {
"Hanyun\Swagger\": "src/"
}
},
"require": {
"php": "^7.3",
"zircote/swagger-php": "^3.1"
}
}
复制代码
修改我们创建的laravel项目下的composer.json
代码语言:javascript复制
"Hanyun\Swagger\": "packages/hanyun/swagger/src"
让我们的项目可以引入我们的扩展包做测试,测试通过之后我们可以把我们的扩展包发布到GitHub上面,然后再发布到packagist.org,这样其他人就可以通过composer引入你的扩展包
"autoload": {
"psr-4": {
"App\": "app/",
"Hanyun\Swagger\": "packages/hanyun/swagger/src",
"Database\Factories\": "database/factories/",
"Database\Seeders\": "database/seeders/"
}
}
复制代码
最终目录结果如下:
代码语言:javascript复制packages
├── hanyun
│ └── swagger
│ └── src
│ ├── Commands
│ │ └── Swagger.php
│ ├── Controllers
│ │ └── SwaggerController.php
│ ├── Facades
│ │ └── Swagger.php
│ ├── Swagger.php
│ ├── SwaggerProvider.php
│ ├── config
│ │ └── swagger.php
│ ├── routes
│ │ └── swagger.php
│ ├── swagger-ui
│ │ └── dist
│ │ ├── favicon-16x16.png
│ │ ├── favicon-32x32.png
│ │ ├── index.html
│ │ ├── oauth2-redirect.html
│ │ ├── swagger-ui-bundle.js
│ │ ├── swagger-ui-bundle.js.map
│ │ ├── swagger-ui-es-bundle-core.js
│ │ ├── swagger-ui-es-bundle-core.js.map
│ │ ├── swagger-ui-es-bundle.js
│ │ ├── swagger-ui-es-bundle.js.map
│ │ ├── swagger-ui-standalone-preset.js
│ │ ├── swagger-ui-standalone-preset.js.map
│ │ ├── swagger-ui.css
│ │ ├── swagger-ui.css.map
│ │ ├── swagger-ui.js
│ │ └── swagger-ui.js.map
│ └── view
│ └── index.blade.php
复制代码
测试
1、项目的/config/app.php 的providers数组里面添加 HanyunSwaggerSwaggerProvider::class
如下所示
```
'providers' => [
//...其他的依赖
HanyunSwaggerSwaggerProvider::class
],
```
复制代码
2、项目的/config/app.php 的aliases数组里面添加 'swagger'=>HanyunSwaggerFacadesSwagger::class
如下所示
'aliases' => [
//... 其他的省略
'swagger'=>HanyunSwaggerFacadesSwagger::class
],
复制代码
3、在项目根目录执行 php artisan vendor:publish
, 找到 [4 ] Provider: HanyunSwaggerSwaggerProvider
这一行,输入前面的数字,按回车
4、执行 php artian make:controller Api/v1/IndexController
生成控制器,修改代码
<?php
namespace AppHttpControllersApiv1;
use AppHttpControllersController;
use IlluminateHttpRequest;
use OpenApiAnnotations as OA;
class IndexController extends Controller
{
//
/**
* @OAGet(
* path="/api/index",
* security={{
* "api_key":{}
* }},
* @OAResponse(response="200", description="
* |参数|说明|备注||||
* |:---:|:---:|:---:|-----|-----|-----|
* |status|状态|['已取消', '等待付款', '下单成功', '付款中'] 取数组索引||||
* ")
* )
*/
public function index(Request $request)
{
return $request->all();
}
}
复制代码
修改 AppHttpControllersController.php
代码如下
<?php
namespace AppHttpControllers;
use IlluminateFoundationAuthAccessAuthorizesRequests;
use IlluminateFoundationBusDispatchesJobs;
use IlluminateFoundationValidationValidatesRequests;
use IlluminateRoutingController as BaseController;
use OpenApiAnnotations as OA;
/**
* @OAOpenApi(
* @OAInfo(
* version="1.0.0",
* title="Swagger Petstore",
* description="This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.",
* termsOfService="http://swagger.io/terms/",
* @OAContact(
* email="apiteam@swagger.io"
* ),
* @OALicense(
* name="Apache 2.0",
* url="http://www.apache.org/licenses/LICENSE-2.0.html"
* )
* ),
* @OAServer(
* description="OpenApi host",
* url="https://petstore.swagger.io/v3"
* ),
* @OAExternalDocumentation(
* description="Find out more about Swagger",
* url="http://swagger.io"
* )
* )
* @OASecurityScheme(
* securityScheme="api_key",
* type="apiKey",
* in="header",
* name="Authorization"
* )
*/
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
}
复制代码
5、修改 config/swagger.php
这个会自动覆盖swagger的默认配置信息
6、在项目根目录执行 php artisan swagger:generate
,生成API
7、项目根目录执行 php artisan serve
,打开 项目文档
发布我们的扩展包
1、提交到GitHub上面
2、发布到ackagist.org
打开ackagist.org 输入你的扩展包的GitHub地址,点击check,就生成了扩展包
具体的swagger文档 ,zircote/swagger-php文档