szhukovwork / openapi-generator
直接从PHP代码(PhpDoc,函数签名和类型提示)和项目(适用于yii2,slim,laravel)生成OpenApi配置。可用于维护大型单体后端的大API文档。
dev-master
2024-02-16 08:55 UTC
Requires
- php: >=7.4
- doctrine/annotations: ^1.6
- phpdocumentor/reflection-docblock: ^4.3|^5.1
- zircote/swagger-php: ^3.0
This package is auto-updated.
Last update: 2024-09-16 10:06:40 UTC
README
这是一个与原始源代码一起工作的OpenApi配置生成器。
此库的主要目的是自动生成大量方法的现有JSON-API
的OpenApi规范。由@maxonrock提出。
OpenApiGenerator
它做什么?
它直接从源代码生成针对您用PHP编写的基于REST JSON的API的OpenApi 3.0规范文件。您不需要手动编写OpenApi规范。
Laravel示例
-
路由
Route::get('/selector/lists', [\App\Http\Controllers\SelectorController::class, 'lists']); Route::post('/selector/select', [\App\Http\Controllers\SelectorController::class, 'select']); Route::get('/selector/goTo', [\App\Http\Controllers\SelectorController::class, 'goTo']); Route::get('/geo/detect', [\App\Http\Controllers\GeoController::class, 'detect']); Route::get('/geo/select', [\App\Http\Controllers\GeoController::class, 'select']);
-
一个控制器
/** * Returns lists of filters * @param Request $request * @return ListsResponse */ public function lists(Request $request) { return new ListsResponse([ // 'persons' => range(1, 15), 'persons' => array_keys(Menu::$personsList), 'tastes' => Menu::$tastes, 'meat' => Menu::$meat, 'pizzas' => Menu::$pizzas, ]); } /** * Makes a selection of pizzas according to criteria * @param \App\Http\Requests\SelectPizzas $request * @return PizzaListItem[] */ public function select(\App\Http\Requests\SelectPizzas $request) { $validated = $request->validated(); return (new Selector())->select( $validated['city'], $validated['persons'], $validated['tastes'] ?? null, $validated['meat'] ?? null, $validated['vegetarian'] ?? false, $validated['maxPrice'] ?? null); }
-
一个请求和两个响应
class SelectPizzas extends FormRequest { public function rules() { // ... return array_merge([ 'city' => ['required', 'string'], 'persons' => ['required', Rule::in(array_keys(Menu::$personsList))], 'vegetarian' => ['boolean'], 'maxPrice' => ['numeric'], 'pizzas' => ['array', Rule::in(array_keys(Menu::$pizzas))], ], $tastes, $meat); } } class ListsResponse extends BaseResponse { /** @var string[] */ public $persons; /** @var string[] */ public $tastes; /** @var string[] */ public $meat; /** @var string[] */ public $pizzas; } class PizzaListItem extends BaseResponse { public string $pizzeria; public string $id; public int $sizeId; public string $name; public float $size; public array $tastes; public array $meat; public float $price; public float $pizzaArea; public float $pizzaCmPrice; public string $thumbnail; public array $ingredients; public int $dough; }
-
代码生成的结果:两个带有描述和
select
参数的端点。┌─────────┬─────────────────┬──────────────────────────┐ │ get │ /selector/lists │ Returns lists of filters │ ├─────────┼─────────────────┼──────────────────────────┤ │ Result (4) │ │ persons │ array of string │ │ │ tastes │ array of string │ │ │ meat │ array of string │ │ │ pizzas │ array of string │ │ └─────────┴─────────────────┴──────────────────────────┘ ┌──────────────────┬──────────────────┬───────────────────────────────────────────────────┐ │ post │ /selector/select │ Makes a selection of pizzas according to criteria │ ├──────────────────┼──────────────────┼───────────────────────────────────────────────────┤ │ Parameters (15) │ │ string │ city │ │ │ string │ persons │ │ │ boolean │ vegetarian │ │ │ number │ maxPrice │ │ │ array │ pizzas │ │ │ boolean │ tastes.cheese │ │ │ boolean │ tastes.sausage │ │ │ boolean │ tastes.spicy │ │ │ boolean │ tastes.mushroom │ │ │ boolean │ tastes.exotic │ │ │ boolean │ meat.chicken │ │ │ boolean │ meat.pork │ │ │ boolean │ meat.beef │ │ │ boolean │ meat.fish │ │ │ boolean │ meat.sauce_meat │ │ ├──────────────────┼──────────────────┼───────────────────────────────────────────────────┤ │ Result (14) │ │ │ array of │ │ │ [*].pizzeria │ string │ │ │ [*].id │ string │ │ │ [*].sizeId │ integer │ │ │ [*].name │ string │ │ │ [*].size │ integer │ │ │ [*].tastes │ array of │ │ │ [*].meat │ array of │ │ │ [*].price │ integer │ │ │ [*].pizzaArea │ integer │ │ │ [*].pizzaCmPrice │ integer │ │ │ [*].thumbnail │ string │ │ │ [*].ingredients │ array of │ │ │ [*].dough │ integer │ │ └──────────────────┴──────────────────┴───────────────────────────────────────────────────┘
如何工作
- 抓取器收集有关API(标签、安全方案和服务器、所有端点)的信息,并包含生成器的设置。抓取器是框架相关的。
- 生成器通过分析源代码填充openapi规范,以端点信息。
- 操作摘要和描述
- 参数和生成器操作的结果是共同的。它只是从抓取器接收信息,并按照抓取器的规则分析代码。
更详细的过程描述在如何工作文档中。
如何使用
调用控制台脚本来生成项目的OpenApi(使用集成)
例如,对于yii2项目
- 在项目上运行解析器以分析文件并检索端点信息
./vendor/bin/openapi-generator scrape --scraper yii2 ./ # And more deeper scan ./vendor/bin/openapi-generator generate --scraper yii2 --inspect ./
- 通过
specification_name.yml
将规范生成到api_docs
文件夹中的yaml文件./vendor/bin/openapi-generator generate --scraper yii2 ./ ./api_docs/ # Or with your own scraper (child of one of basic scrapers) ./vendor/bin/openapi-generator generate --scraper components/api/OpenApiScraper.php ./ ./api_docs/
- 部署具有规范的swagger(例如,端口8091上的api_docs/main.yml)
docker run -p 8091:8080 --rm -e URL=./apis/main.yaml -v $(pwd):/usr/share/nginx/html/apis/ swaggerapi/swagger-ui:v4.15.2
更详细的描述在如何使用文档中。
集成
有一些集成:Yii2、Laravel、Slim。详细信息在集成文档中。您可以为您自己的框架或项目编写自己的集成。
扩展
新的抓取器
您可以使用(或扩展)预定义的抓取器(请参阅集成)或从头开始创建自己的抓取器(扩展DefaultScraper
),它应返回一个包含您的API端点的列表。此外,您的抓取器还应提供标签、安全方案等。
抓取器应返回包含以下内容的规范列表(例如,API版本列表):
- meta - 规范的版本/描述/外部文档。
- servers - 服务器列表(基本URL)。
- tags - 带有描述和其他属性的标签列表(端点的类别)。
- securitySchemes - 安全方案列表(授权类型)。
- endpoints - API端点列表(单独的回调)。
关于抓取器结果的详细信息:请参阅另一份文档。
设置
DefaultGenerator提供了用于调整生成器的设置列表。
用法
$generator->changeSetting(DefaultGenerator::CHANGE_GET_TO_POST_FOR_COMPLEX_PARAMETERS, true);
默认情况下,它们都是禁用的。
限制
- 仅支持查询参数(
url?param1=...¶m2=...
)或JSON格式的请求体参数({data: 123}
)。 - 仅支持HTTP 200响应类型。
- 不支持参数的
format
、example
和其他验证器。
待办事项
- 对一个端点支持的操作有限(GET/POST/PUT/DELETE/...)。
- 部分支持请求体参数(当参数是复杂对象时)。
- 部分支持不同的响应(带有不同的HTTP状态码)。
- 将类类型提取到单独的组件中(到openapi组件)。
- 支持除JSON之外的请求/响应类型。
- 部分支持使用
@paramFormat
指定参数格式。 - 支持动态模型中的动态操作参数。
- 切换3.0/3.1版本(https://openapis.org.cn/blog/2021/02/16/migrating-from-openapi-3-0-to-3-1-0)