手把手教你從零開始寫一個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的配置檔案,
檔案位置
/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"
]
],
];
建立檢視
檔案位置
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>
建立控制器,用於顯示文件介面
檔案位置
packages/hanyun/swagger/src/Controllers/SwaggerController.php
<?php
namespace Hanyun\Swagger\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class SwaggerController extends Controller
{
//
public function index()
{
return view('swagger-ui.index');
}
}
建立路由
檔案位置
packages/hanyun/swagger/src/routes/swagger.php
<?php
/**
* User: Only
* Time: 17:04
*/
use Illuminate\Support\Facades\Route;
Route::get('/swagger', [\Hanyun\Swagger\Controllers\SwaggerController::class, 'index']);
建立console命令用於生成文件
檔案位置
packages/hanyun/swagger/src/Commands/Swagger.php
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
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 = \OpenApi\scan(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\\\\n\s{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;
}
}
建立門面
檔案位置
packages/hanyun/swagger/src/Facades/Swagger.php
<?php
/**
* User: Only
* Time: 16:39
*/
namespace Hanyun\Swagger\Facades;
use Illuminate\Support\Facades\Facade;
class Swagger extends Facade
{
protected static function getFacadeAccessor()
{
return 'swagger';
}
}
建立provider用於釋出擴充套件
檔案位置
packages/hanyun/swagger/src/SwaggerProvider.php
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
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 = \OpenApi\scan(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\\\\n\s{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
{
"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
"Hanyun\\Swagger\\": "packages/hanyun/swagger/src"
讓我們的專案可以引入我們的擴充套件包做測試,測試通過之後我們可以把我們的擴充套件包釋出到GitHub上面,然後再發布到https://packagist.org,這樣其他人就可以通過composer引入你的擴充套件包
"autoload": {
"psr-4": {
"App\\": "app/",
"Hanyun\\Swagger\\": "packages/hanyun/swagger/src",
"Database\\Factories\\": "database/factories/",
"Database\\Seeders\\": "database/seeders/"
}
}
最終目錄結果如下:
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陣列裡面新增 \Hanyun\Swagger\SwaggerProvider::class
如下所示
```
'providers' => [
//...其他的依賴
\Hanyun\Swagger\SwaggerProvider::class
],
```
2、專案的/config/app.php 的aliases陣列裡面新增 'swagger'=>\Hanyun\Swagger\Facades\Swagger::class
如下所示
'aliases' => [
//... 其他的省略
'swagger'=>\Hanyun\Swagger\Facades\Swagger::class
],
3、在專案根目錄執行 php artisan vendor:publish
, 找到 [4 ] Provider: Hanyun\Swagger\SwaggerProvider
這一行,輸入前面的數字,按回車
4、執行 php artian make:controller Api/v1/IndexController
生成控制器,修改程式碼
<?php
namespace App\Http\Controllers\Api\v1;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use OpenApi\Annotations as OA;
class IndexController extends Controller
{
//
/**
* @OA\Get(
* path="/api/index",
* security={{
* "api_key":{}
* }},
* @OA\Response(response="200", description="
* |引數|說明|備註||||
* |:---:|:---:|:---:|-----|-----|-----|
* |status|狀態|['已取消', '等待付款', '下單成功', '付款中'] 取陣列索引||||
* ")
* )
*/
public function index(Request $request)
{
return $request->all();
}
}
修改 App\Http\Controllers\Controller.php
程式碼如下
<?php
namespace App\Http\Controllers;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
use OpenApi\Annotations as OA;
/**
* @OA\OpenApi(
* @OA\Info(
* 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/",
* @OA\Contact(
* email="apiteam@swagger.io"
* ),
* @OA\License(
* name="Apache 2.0",
* url="http://www.apache.org/licenses/LICENSE-2.0.html"
* )
* ),
* @OA\Server(
* description="OpenApi host",
* url="https://petstore.swagger.io/v3"
* ),
* @OA\ExternalDocumentation(
* description="Find out more about Swagger",
* url="http://swagger.io"
* )
* )
* @OA\SecurityScheme(
* 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文件
github地址 歡迎大家star和fork
本作品採用《CC 協議》,轉載必須註明作者和本文連結