soft-chen / laravel-openapi
根据 Laravel 路由和控制器 结合 DocBlocks 生成 OpenAPI 文档。
Requires
- php: ^8.2
- illuminate/contracts: ^11.0||^12.0||^13.0
- illuminate/support: ^11.0||^12.0||^13.0
- php-openapi/openapi: ^2.1
- phpdocumentor/reflection-docblock: ^5.6
- spatie/laravel-package-tools: ^1.16
Requires (Dev)
- larastan/larastan: ^3.0
- laravel/pint: ^1.14
- phpstan/extension-installer: ^1.4
- phpstan/phpstan-deprecation-rules: ^2.0
This package is not auto-updated.
Last update: 2026-04-20 00:32:45 UTC
README
soft-chen/laravel-openapi 用于根据 Laravel 路由和控制器 DocBlock 生成基础 OpenAPI 文档对象。
本包保持轻量:仅注册 LaravelOpenApiServiceProvider 并支持发布 config/openapi.php 配置文件,不包含命令、视图、迁移或门面。
环境要求
- PHP
^8.2 - Laravel
^11.0、^12.0或^13.0
安装
composer require soft-chen/laravel-openapi
Laravel 会通过 Composer 自动发现并注册服务提供者。若项目关闭了包自动发现,可手动注册:
// bootstrap/providers.php
return [
SoftChen\LaravelOpenApi\Providers\LaravelOpenApiServiceProvider::class,
];
发布配置
本包配置发布 tag 固定为 laravel-openapi-config。
php artisan vendor:publish --tag="laravel-openapi-config"
也可以指定 Provider 发布:
php artisan vendor:publish --provider="SoftChen\LaravelOpenApi\Providers\LaravelOpenApiServiceProvider" --tag="laravel-openapi-config"
发布后会生成 config/openapi.php。默认配置示例:
return [
'default' => [
'title' => 'API Docs',
'description' => 'API documentation',
'version' => '1.0.0',
'handler' => null,
'cache_enable' => true,
'cache' => [
'ttl' => 86400,
'store' => null,
],
'needLoginMiddleware' => [
// 'admin',
],
'openapi' => [
'openapi' => '3.0.3',
// 'components' => [
// 'securitySchemes' => [
// 'Authorization' => [
// 'type' => 'apiKey',
// 'in' => 'header',
// 'name' => 'Authorization',
// ],
// ],
// ],
// 'security' => [
// ['Authorization' => []],
// ],
],
'route' => [
'include' => [
// 'api/*',
// 'api.*',
],
'exclude' => [
// '_ignition/*',
],
],
],
];
配置文件第一层 key 是文档分组名。调用生成器时不传分组名会默认使用第一个分组。
生成文档
use SoftChen\LaravelOpenApi\OpenApiGenerator;
$openapi = OpenApiGenerator::generate();
// 指定分组
$adminOpenapi = OpenApiGenerator::generate('default');
返回值是 SoftChen\LaravelOpenApi\OpenApiDocument 对象,内部保存 openapiphp\openapi\spec\OpenApi,可按项目需要读取字段、转换为数组、JSON、写入文件或继续二次处理。
$document = OpenApiGenerator::generate('default');
$title = $document->info->title;
$pathItem = $document->paths['/users'] ?? null;
$operation = $pathItem?->get;
$response = $operation?->responses['200'] ?? null;
$array = $document->toArray();
$json = $document->toJson(JSON_PRETTY_PRINT);
$openApi = $document->toOpenApi();
如果希望直接生成数组或 JSON,可以使用生成器提供的快捷方法:
$array = OpenApiGenerator::toArray('default');
$json = OpenApiGenerator::toJson('default', JSON_PRETTY_PRINT);
底层 openapiphp\openapi\spec\OpenApi 由 php-openapi/openapi 提供,字段名称与 OpenAPI Specification 保持一致。未显式建模或 x-* 扩展字段也会由该包按规范处理。
return response()->json(OpenApiGenerator::toArray('default'));
文档缓存
为减少重复扫描路由和反射解析的开销,生成器默认会将每个文档分组的结果缓存 86400 秒。
'cache_enable' => true,
'cache' => [
'ttl' => 86400,
'store' => null,
],
cache_enable默认开启,关闭后将完全跳过缓存逻辑。APP_ENV=local时也会直接跳过缓存,便于本地修改路由、控制器和 DocBlock 后即时生效。cache.ttl单位为秒,设置为0或更小值时表示关闭缓存。cache.store为空时使用 Laravel 默认缓存驱动,也可以指定单独的 store。
如果线上发布后需要主动清掉文档缓存,可以直接调用:
use SoftChen\LaravelOpenApi\OpenApiGenerator;
OpenApiGenerator::clearCache('default');
// 多域名场景下也可以显式传入 server URL
OpenApiGenerator::clearCache('default', 'https://api.example.com');
未传第二个参数时,会按当前请求根地址或 app.url 生成缓存 key。
路由过滤
route.include 和 route.exclude 同时支持路由 URI 与路由名称,匹配规则使用 Laravel Str::is(),因此可以使用 * 通配符。
'route' => [
'include' => [
'api/*',
'admin.*',
],
'exclude' => [
'api/internal/*',
],
],
include 为空时表示纳入全部路由,exclude 命中的路由会被剔除。
按 Middleware 标记登录
如果只有部分路由需要登录,可以配置 needLoginMiddleware。生成器会检查 route:list --json 输出里的 middleware 字段,只有命中这些 middleware 的路由才会带上 OpenAPI security。
'needLoginMiddleware' => 'admin',
'openapi' => [
'components' => [
'securitySchemes' => [
'Authorization' => [
'type' => 'apiKey',
'in' => 'header',
'name' => 'Authorization',
],
],
],
'security' => [
['Authorization' => []],
],
],
needLoginMiddleware 支持字符串、数组和 * 通配符;例如 ['admin', 'auth:*']。配置该项后,openapi.security 会作为“需要登录的接口”的默认鉴权要求,未命中的路由不会继承这段 security。
DocBlock 说明
生成器会读取控制器类和方法的 DocBlock:
- 控制器类摘要会作为 OpenAPI
tags名称。 - 控制器方法摘要会作为接口
summary。 - 控制器方法描述会作为接口
description。
/**
* 用户管理
*/
class UserController
{
/**
* 用户列表
*
* 获取后台用户分页列表。
*/
public function index()
{
//
}
}
OpenAPI 根配置
openapi 配置项会合并到 OpenAPI 根节点,可用于补充 servers、externalDocs、components、security 等信息。termsOfService、contact、license 属于 OpenAPI info 对象,建议写到 openapi.info 下。设置 needLoginMiddleware 后,openapi.security 会改为按命中的路由逐个写入,不再作为全局默认值输出。未配置 servers 时,生成器会默认使用当前请求根地址;如果当前没有 HTTP 请求,则回退到 app.url。
'openapi' => [
'openapi' => '3.0.3',
'servers' => [
['url' => 'https://api.example.com'],
],
'info' => [
'termsOfService' => 'https://example.com/terms',
'contact' => [
'name' => 'API Support',
'email' => 'support@example.com',
],
'license' => [
'name' => 'MIT',
'url' => 'https://opensource.org/licenses/MIT',
],
],
'components' => [
'securitySchemes' => [
'Authorization' => [
'type' => 'apiKey',
'in' => 'header',
'name' => 'Authorization',
'description' => '通用请求头中传入 Authorization,例如 Bearer {token}',
],
],
],
'security' => [
['Authorization' => []],
],
],
如果你的项目是通过通用请求头传入 Authorization,可以直接使用上面的示例。这样生成的 OpenAPI 文档会声明全局鉴权方案,并应用到所有接口。
生成器会维护 info.title、info.description、info.version 以及 paths、tags。如果只需要补充 info 里的其他字段,可以通过 openapi.info 配置;为兼容旧配置,写在 openapi 根层的 termsOfService、contact、license 也会自动归并到 info。
如果你没有显式配置 openapi.servers,生成器会自动补一个默认值:
- HTTP 请求上下文里使用当前请求根地址,例如
https://api.example.com - CLI 或其他拿不到请求的场景回退到 Laravel
app.url
自定义处理器
如果需要补充请求体、响应结构、鉴权信息,或者按权限裁剪接口,可配置一个处理器:
'handler' => App\OpenApi\AdminOpenApiHandler::class,
推荐继承 SoftChen\LaravelOpenApi\Handlers\OpenApiHandler,这样可以直接使用封装好的公共方法,而不需要自己处理底层对象细节。旧版 transformer 配置键和 OpenApiTransformer 仍然兼容,但后续更建议统一迁移到 handler。
namespace App\OpenApi;
use openapiphp\openapi\spec\Schema;
use SoftChen\LaravelOpenApi\Handlers\OpenApiHandler;
class AdminOpenApiHandler extends OpenApiHandler
{
protected function process(): void
{
$this->describeOperation('/api/users/{id}', 'get', '用户详情', '根据用户 ID 获取后台用户详情。');
$this->upsertPathParameter('/api/users/{id}', 'get', 'id', '用户 ID。', new Schema([
'type' => 'integer',
'format' => 'int64',
]));
}
}
基础 OpenApiHandler 当前封装了这些常用公共方法。下面每个方法都默认在子类的 process() 中调用。
如果你的场景需要按数据库权限、租户配置或其他业务规则去掉部分接口,可以直接在 process() 里调用删除 helper:
protected function process(): void
{
if (! $this->shouldExpose('users.export')) {
$this->removeOperation('/api/users/export', 'post');
}
if (! $this->shouldExpose('internal.docs')) {
$this->removePath('/api/internal/docs');
}
}
removeOperation()
用途:删除某个路径下的单个 HTTP 接口;如果该路径下已经没有其他方法,会自动把整个 path 一并移除。
方法签名:
removeOperation(string $path, string $method): static
示例:
$this->removeOperation('/api/users/export', 'post');
removePath()
用途:删除整个 OpenAPI path 以及其下的所有接口定义。
方法签名:
removePath(string $path): static
示例:
$this->removePath('/api/internal/docs');
describeOperation()
用途:同时设置接口的 summary 和 description,适合快速补齐接口中文说明。
方法签名:
describeOperation(string $path, string $method, ?string $summary = null, ?string $description = null): static
参数说明:
$path:OpenAPI 路径,例如/api/users/{id}$method:HTTP 方法,例如get、post$summary:接口标题,可传null$description:接口详细描述,可传null
示例:
$this->describeOperation(
'/api/users/{id}',
'get',
'用户详情',
'根据用户 ID 获取后台用户详情。'
);
setOperationSummary()
用途:只设置接口标题,不改动接口描述。
方法签名:
setOperationSummary(string $path, string $method, string $summary): static
示例:
$this->setOperationSummary('/api/users', 'get', '用户列表');
setOperationDescription()
用途:只设置接口详细描述,不改动接口标题。
方法签名:
setOperationDescription(string $path, string $method, string $description): static
示例:
$this->setOperationDescription('/api/users', 'get', '分页获取后台用户列表,支持关键词搜索。');
upsertQueryParameter()
用途:新增或更新查询参数。如果参数已存在,会按 name + in 合并更新。
方法签名:
upsertQueryParameter(
string $path,
string $method,
string $name,
string $description,
array|Schema $schema = ['type' => 'string'],
bool $required = false,
): static
参数说明:
$name:查询参数名,例如page$description:参数中文说明$schema:参数类型定义,推荐传openapiphp\openapi\spec\Schema$required:是否必填,默认false
示例:
use openapiphp\openapi\spec\Schema;
$this->upsertQueryParameter('/api/users', 'get', 'page', '页码,从 1 开始。', new Schema([
'type' => 'integer',
'minimum' => 1,
]));
$this->upsertQueryParameter('/api/users', 'get', 'keyword', '搜索关键词。');
upsertPathParameter()
用途:新增或更新路径参数。该方法会自动把参数标记为 required = true。
方法签名:
upsertPathParameter(
string $path,
string $method,
string $name,
string $description,
array|Schema $schema = ['type' => 'string'],
): static
示例:
use openapiphp\openapi\spec\Schema;
$this->upsertPathParameter('/api/users/{id}', 'get', 'id', '用户 ID。', new Schema([
'type' => 'integer',
'format' => 'int64',
]));
setJsonRequestBody()
用途:设置 application/json 请求体,适合 POST、PUT、PATCH 这类接口。
方法签名:
setJsonRequestBody(
string $path,
string $method,
array|Schema $schema,
bool $required = true,
?string $description = null,
): static
参数说明:
$schema:请求体 schema,可传 OpenAPI schema 数组- 推荐传
openapiphp\openapi\spec\Schema对象 $required:请求体是否必填$description:请求体说明
示例:
use openapiphp\openapi\spec\Schema;
$this->setJsonRequestBody('/api/users', 'post', new Schema([
'type' => 'object',
'required' => ['name', 'email'],
'properties' => [
'name' => [
'type' => 'string',
'description' => '用户名称。',
],
'email' => [
'type' => 'string',
'format' => 'email',
'description' => '登录邮箱。',
],
],
]), true, '创建用户请求体。');
setResponseDescription()
用途:设置指定响应状态码的描述;如果该响应不存在,会自动创建。
方法签名:
setResponseDescription(string $path, string $method, string|int $statusCode, string $description): static
示例:
$this->setResponseDescription('/api/users', 'post', 200, '创建成功。');
$this->setResponseDescription('/api/users/{id}', 'delete', 404, '用户不存在。');
document()
用途:获取当前 OpenApiDocument 对象。适合你需要直接访问底层完整文档时使用。
方法签名:
document(): OpenApiDocument
示例:
$document = $this->document();
$openApi = $document->toOpenApi();
context()
用途:获取当前转换上下文,可访问当前配置分组、配置内容和路由列表。
方法签名:
context(): OpenApiHandlerContext
示例:
$key = $this->context()->key;
$route = $this->context()->routeByName('users.show');
operation()
用途:读取某个接口对应的底层 Operation 对象;如果不存在,返回 null。
方法签名:
operation(string $path, string $method): ?Operation
示例:
$operation = $this->operation('/api/users/{id}', 'get');
pathItem()
用途:读取某个路径对应的底层 PathItem 对象;如果不存在,返回 null。
方法签名:
pathItem(string $path): ?PathItem
示例:
$pathItem = $this->pathItem('/api/users/{id}');
更完整的示例请看 examples/AdminOpenApiHandler.php,其中包含:
- 给
GET /api/users添加接口描述。 - 给
keyword、page、per_page查询参数添加说明。 - 给
GET /api/users/{id}的id路径参数添加说明。 - 给
POST /api/users添加 JSON 请求体字段说明。
路径需要使用生成后的 OpenAPI path,例如 Laravel 路由 api/users/{id} 对应 /api/users/{id}。
转换时传入的是 SoftChen\LaravelOpenApi\Documents\OpenApiDocument 对象和 SoftChen\LaravelOpenApi\Handlers\OpenApiHandlerContext 对象。若继承基础 OpenApiHandler,可以通过 document() 和 context() 访问它们。
$array = OpenApiGenerator::generate('default')->toArray();
$json = OpenApiGenerator::generate('default')->toJson(JSON_PRETTY_PRINT);
开发检查
composer analyse
composer format
更新日志
请查看 CHANGELOG。
许可证
MIT License. 请查看 LICENSE.md。