# laravel-openapi **Repository Path**: soft-chen/laravel-openapi ## Basic Information - **Project Name**: laravel-openapi - **Description**: Laravel OpenApi - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-04-20 - **Last Updated**: 2026-04-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Laravel OpenAPI [![Latest Version on Packagist](https://img.shields.io/packagist/v/soft-chen/laravel-openapi.svg?style=flat-square)](https://packagist.org/packages/soft-chen/laravel-openapi) [![Total Downloads](https://img.shields.io/packagist/dt/soft-chen/laravel-openapi.svg?style=flat-square)](https://packagist.org/packages/soft-chen/laravel-openapi) `soft-chen/laravel-openapi` 用于根据 Laravel 路由和控制器 DocBlock 生成基础 OpenAPI 文档对象。 本包保持轻量:仅注册 `LaravelOpenApiServiceProvider` 并支持发布 `config/openapi.php` 配置文件,不包含命令、视图、迁移或门面。 ## 环境要求 - PHP `^8.2` - Laravel `^11.0`、`^12.0` 或 `^13.0` ## 安装 ```bash composer require soft-chen/laravel-openapi ``` Laravel 会通过 Composer 自动发现并注册服务提供者。若项目关闭了包自动发现,可手动注册: ```php // bootstrap/providers.php return [ SoftChen\LaravelOpenApi\Providers\LaravelOpenApiServiceProvider::class, ]; ``` ## 发布配置 本包配置发布 tag 固定为 `laravel-openapi-config`。 ```bash php artisan vendor:publish --tag="laravel-openapi-config" ``` 也可以指定 Provider 发布: ```bash php artisan vendor:publish --provider="SoftChen\LaravelOpenApi\Providers\LaravelOpenApiServiceProvider" --tag="laravel-openapi-config" ``` 发布后会生成 `config/openapi.php`。默认配置示例: ```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 是文档分组名。调用生成器时不传分组名会默认使用第一个分组。 ## 生成文档 ```php use SoftChen\LaravelOpenApi\OpenApiGenerator; $openapi = OpenApiGenerator::generate(); // 指定分组 $adminOpenapi = OpenApiGenerator::generate('default'); ``` 返回值是 `SoftChen\LaravelOpenApi\OpenApiDocument` 对象,内部保存 `openapiphp\openapi\spec\OpenApi`,可按项目需要读取字段、转换为数组、JSON、写入文件或继续二次处理。 ```php $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,可以使用生成器提供的快捷方法: ```php $array = OpenApiGenerator::toArray('default'); $json = OpenApiGenerator::toJson('default', JSON_PRETTY_PRINT); ``` 底层 `openapiphp\openapi\spec\OpenApi` 由 `php-openapi/openapi` 提供,字段名称与 OpenAPI Specification 保持一致。未显式建模或 `x-*` 扩展字段也会由该包按规范处理。 ```php return response()->json(OpenApiGenerator::toArray('default')); ``` ## 文档缓存 为减少重复扫描路由和反射解析的开销,生成器默认会将每个文档分组的结果缓存 `86400` 秒。 ```php 'cache_enable' => true, 'cache' => [ 'ttl' => 86400, 'store' => null, ], ``` - `cache_enable` 默认开启,关闭后将完全跳过缓存逻辑。 - `APP_ENV=local` 时也会直接跳过缓存,便于本地修改路由、控制器和 DocBlock 后即时生效。 - `cache.ttl` 单位为秒,设置为 `0` 或更小值时表示关闭缓存。 - `cache.store` 为空时使用 Laravel 默认缓存驱动,也可以指定单独的 store。 如果线上发布后需要主动清掉文档缓存,可以直接调用: ```php 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()`,因此可以使用 `*` 通配符。 ```php 'route' => [ 'include' => [ 'api/*', 'admin.*', ], 'exclude' => [ 'api/internal/*', ], ], ``` `include` 为空时表示纳入全部路由,`exclude` 命中的路由会被剔除。 ## 按 Middleware 标记登录 如果只有部分路由需要登录,可以配置 `needLoginMiddleware`。生成器会检查 `route:list --json` 输出里的 `middleware` 字段,只有命中这些 middleware 的路由才会带上 OpenAPI `security`。 ```php '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`。 ```php /** * 用户管理 */ 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`。 ```php '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` ## 自定义处理器 如果需要补充请求体、响应结构、鉴权信息,或者按权限裁剪接口,可配置一个处理器: ```php 'handler' => App\OpenApi\AdminOpenApiHandler::class, ``` 推荐继承 `SoftChen\LaravelOpenApi\Handlers\OpenApiHandler`,这样可以直接使用封装好的公共方法,而不需要自己处理底层对象细节。旧版 `transformer` 配置键和 `OpenApiTransformer` 仍然兼容,但后续更建议统一迁移到 `handler`。 ```php 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: ```php 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 一并移除。 方法签名: ```php removeOperation(string $path, string $method): static ``` 示例: ```php $this->removeOperation('/api/users/export', 'post'); ``` ### `removePath()` 用途:删除整个 OpenAPI path 以及其下的所有接口定义。 方法签名: ```php removePath(string $path): static ``` 示例: ```php $this->removePath('/api/internal/docs'); ``` ### `describeOperation()` 用途:同时设置接口的 `summary` 和 `description`,适合快速补齐接口中文说明。 方法签名: ```php 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` 示例: ```php $this->describeOperation( '/api/users/{id}', 'get', '用户详情', '根据用户 ID 获取后台用户详情。' ); ``` ### `setOperationSummary()` 用途:只设置接口标题,不改动接口描述。 方法签名: ```php setOperationSummary(string $path, string $method, string $summary): static ``` 示例: ```php $this->setOperationSummary('/api/users', 'get', '用户列表'); ``` ### `setOperationDescription()` 用途:只设置接口详细描述,不改动接口标题。 方法签名: ```php setOperationDescription(string $path, string $method, string $description): static ``` 示例: ```php $this->setOperationDescription('/api/users', 'get', '分页获取后台用户列表,支持关键词搜索。'); ``` ### `upsertQueryParameter()` 用途:新增或更新查询参数。如果参数已存在,会按 `name + in` 合并更新。 方法签名: ```php 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` 示例: ```php 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`。 方法签名: ```php upsertPathParameter( string $path, string $method, string $name, string $description, array|Schema $schema = ['type' => 'string'], ): static ``` 示例: ```php 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` 这类接口。 方法签名: ```php 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`:请求体说明 示例: ```php 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()` 用途:设置指定响应状态码的描述;如果该响应不存在,会自动创建。 方法签名: ```php setResponseDescription(string $path, string $method, string|int $statusCode, string $description): static ``` 示例: ```php $this->setResponseDescription('/api/users', 'post', 200, '创建成功。'); $this->setResponseDescription('/api/users/{id}', 'delete', 404, '用户不存在。'); ``` ### `document()` 用途:获取当前 `OpenApiDocument` 对象。适合你需要直接访问底层完整文档时使用。 方法签名: ```php document(): OpenApiDocument ``` 示例: ```php $document = $this->document(); $openApi = $document->toOpenApi(); ``` ### `context()` 用途:获取当前转换上下文,可访问当前配置分组、配置内容和路由列表。 方法签名: ```php context(): OpenApiHandlerContext ``` 示例: ```php $key = $this->context()->key; $route = $this->context()->routeByName('users.show'); ``` ### `operation()` 用途:读取某个接口对应的底层 `Operation` 对象;如果不存在,返回 `null`。 方法签名: ```php operation(string $path, string $method): ?Operation ``` 示例: ```php $operation = $this->operation('/api/users/{id}', 'get'); ``` ### `pathItem()` 用途:读取某个路径对应的底层 `PathItem` 对象;如果不存在,返回 `null`。 方法签名: ```php pathItem(string $path): ?PathItem ``` 示例: ```php $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()` 访问它们。 ```php $array = OpenApiGenerator::generate('default')->toArray(); $json = OpenApiGenerator::generate('default')->toJson(JSON_PRETTY_PRINT); ``` ## 开发检查 ```bash composer analyse composer format ``` ## 更新日志 请查看 [CHANGELOG](CHANGELOG.md)。 ## 许可证 MIT License. 请查看 [LICENSE.md](LICENSE.md)。