onmoon / openapi-server-bundle
一个用于从OpenAPI v3规范创建功能齐全的API服务器的Symfony扩展包
Requires
- php: ^8.1
- ext-json: *
- cebe/php-openapi: 1.6.99
- league/openapi-psr7-validator: ^0.22.0
- lukasoppermann/http-status: ^4.0
- nikic/php-parser: ^4.19
- nyholm/psr7: ^1.5
- phpdocumentor/reflection-docblock: ^5.3
- sspat/reserved-words: ^3.0
- symfony/cache: ^6.4|^7.0
- symfony/cache-contracts: ^3.5
- symfony/config: ^6.4|^7.0
- symfony/console: ^6.4|^7.0
- symfony/dependency-injection: ^6.4|^7.0
- symfony/event-dispatcher: ^6.4|^7.0
- symfony/http-kernel: ^6.4|^7.0
- symfony/psr-http-message-bridge: ^6.4|^7.0
- symfony/routing: ^6.4|^7.0
- symfony/yaml: ^6.4|^7.0
- thecodingmachine/safe: ^1.3|^2
Requires (Dev)
- doctrine/coding-standard: ^12.0
- matthiasnoback/symfony-config-test: ^5.1
- matthiasnoback/symfony-dependency-injection-test: ^5.1
- phpstan/phpstan: ^1.11
- phpstan/phpstan-phpunit: ^1.4
- phpstan/phpstan-strict-rules: ^1.6
- phpunit/phpunit: ^10.5
- roave/infection-static-analysis-plugin: ^1.35
- squizlabs/php_codesniffer: ^3.10
- symfony/browser-kit: ^6.4|^7.0
- symfony/dom-crawler: ^6.4|^7.0
- symfony/framework-bundle: ^6.4|^7.0
- thecodingmachine/phpstan-safe-rule: ^1.2
- vimeo/psalm: ^5.24
- dev-master
- 4.3.2
- 4.3.1
- 4.3.0
- 4.2.0
- 4.1.0
- 4.0.0
- 3.2.0
- 3.1.1
- 3.1.0
- 3.0.1
- 3.0.0
- 2.1.0
- 2.0.0
- 1.0.0
- 0.9.1
- 0.9.0
- 0.8.0
- 0.7.0
- 0.6.2
- 0.6.1
- 0.6.0
- 0.5.0
- 0.4.1
- 0.4.0
- 0.3.0
- dev-update-dev-tools
- dev-98-filegenerator-tests
- dev-148-api-controller-test
- dev-109-tests-for-codegenerator-phpparsergenerators-dtocodegenerator
This package is auto-updated.
Last update: 2024-08-29 14:39:13 UTC
README
关于
此扩展包可以生成实现API时编写的大多数常见样板代码。代码是从OpenAPI规范生成的。
以下问题将由扩展包自动处理
- 路由生成和路由
- 根据规范验证传入的请求
- 严格类型请求和响应对象以及API调用处理程序接口
- 将请求对象传递给包含API调用处理逻辑的您的代码
- 序列化返回的响应对象
您只需实现API调用处理程序接口并返回提供的响应对象即可。
安装
安装此扩展的首选方式是通过composer。
运行
composer require cebe/php-openapi:dev-php-81-compat onmoon/openapi-server-bundle
然后,将扩展包类添加到您的config/bundles.php
<?php return [ OnMoon\OpenApiServerBundle\OpenApiServerBundle::class => ['all' => true], ];
用法
您可以通过向您的/config/packages/open_api_server.yaml
中添加以下参数来配置扩展包
open_api_server: #root_name_space: App\Generated # Namespace for DTOs and Api Interfaces ## The bundle will try to derive the paths for the generated files from the namespace. If you do not want them to be ## stored in \App namespace or if you \App namespace is not in %kernel.project_dir%/src/, then you ## can specify this path manually: #root_path: %kernel.project_dir%/src/Generated #language_level: 8.0.0 # minimum PHP version the generated code should be compatible with #generated_dir_permissions: 0755 # permissions for the generated directories #full_doc_blocks: false # whether to generate DocBlocks for typed variables and params #send_nulls: false # return null values in responses if property is nullable and not required #skip_http_codes: [] # List of response codes ignored while parsing specification. ## Can be any open api response code ( like 500, "5XX", "default"), or ## "5**", which will include both numeric (500) and XX ("5XX") codes. ## Might be useful if you want to generate error responses in event listener. specs: petstore: path: '../spec/petstore.yaml' # path to OpenApi specification type: yaml # Specification format, either yaml or json. If omitted, the specification file extension will be used. name_space: PetStore # Namespace for generated DTOs and Interfaces media_type: 'application/json' # media type from the specification files to use for generating request and response DTOs #date_time_class: '\Carbon\CarbonImmutable' # FQCN which implements \DateTimeInterface. ## If set up, then generated DTOs will return instances of this class in DateTime parameters
使用标准的resource
关键字和open_api
类型将您的OpenApi规范添加到应用程序路由配置文件中
petstore-api: resource: 'petstore' # This should be same as in specs section of /config/packages/open_api_server.yaml type: open_api prefix: '/api' # Add this standard parameter to add base path to all paths in api name_prefix: 'petstore_' # This will add a prefix to route names
OpenAPI架构的要求
为了使扩展包与您的规范正确工作,它们应该使用OpenAPI 3.0格式编写,并且每个操作都必须有一个唯一的operationId
。
目前也存在以下限制
number
没有format
时被视为浮点数- 路径和查询参数中仅允许使用标量类型
- 在选择路由时,路径参数模式中的部分匹配模式被忽略,仅使用
^...$
模式 - 如果路径参数中指定了模式,则忽略类型和格式生成的模式
- 请求和响应体架构只能使用一个媒体类型。见:https://swagger.org.cn/docs/specification/media-types/
生成API服务器代码
有两个控制台命令与生成的API服务器代码一起使用
- 生成服务器代码:
php bin/console open-api:generate
- 删除服务器代码:
php bin/console open-api:delete
大多数时候您应该使用generate
命令。它将清除扩展包缓存,如果存在,则删除旧的服务器代码,并生成新的代码。
小心使用generate和delete命令,它们将删除您在/config/packages/open_api_server.yaml
文件中指定的root_path
目录中的所有内容。该目录应不包含任何文件,除了此扩展包生成的代码,因为它将在每次生成API服务器代码时被删除。
对于规范中描述的每个操作,都会生成一个API调用处理程序接口,您应该实现它来处理API调用。
实现API调用处理程序接口
给定以下生成的API处理程序接口
<?php declare (strict_types=1); namespace App\Generated\Apis\PetStore\ShowPetById; use OnMoon\OpenApiServerBundle\Interfaces\RequestHandler; use App\Generated\Apis\PetStore\ShowPetById\Dto\Request\ShowPetByIdRequestDto; use App\Generated\Apis\PetStore\ShowPetById\Dto\Response\ShowPetByIdResponse; /** * This interface was automatically generated * You should not change it manually as it will be overwritten */ interface ShowPetById extends RequestHandler { /** Info for a specific pet */ public function showPetById(ShowPetByIdRequestDto $request) : ShowPetByIdResponse; }
您的API调用处理程序可能看起来像这样
<?php namespace App\Api; use App\Repository\PetRepository; use App\Generated\Apis\PetStore\ShowPetById\Dto\Request\ShowPetByIdRequestDto; use App\Generated\Apis\PetStore\ShowPetById\Dto\Response\OK\ShowPetByIdResponseDto; use App\Generated\Apis\PetStore\ShowPetById\Dto\Response\ShowPetByIdResponse; use App\Generated\Apis\PetStore\ShowPetById\ShowPetById; class ShowPetByIdHandler implements ShowPetById { private PetRepository $pets; public function __construct(PetRepository $pets) { $this->pets = $pets; } public function showPetById(ShowPetByIdRequestDto $request) : ShowPetByIdResponse { $petId = $request->getPathParameters()->getPetId(); $pet = $this->pets->getById($petId); return new ShowPetByIdResponseDto($pet->id(), $pet->name()); } }
此外,您的API调用处理程序可以实现以下接口
\OnMoon\OpenApiServerBundle\Interfaces\SetClientIp
- 如果它需要客户端IP地址\OnMoon\OpenApiServerBundle\Interfaces\SetRequest
- 如果它需要Symfony请求对象\OnMoon\OpenApiServerBundle\Interfaces\GetResponseCode
- 如果它需要指定自定义HTTP响应代码
使用DTO映射器
如果您想将Doctrine实体或其他业务逻辑类作为API响应的源,您可以使用DTO映射器轻松地将内容复制到DTO中。
使用以下命令安装:
composer require onmoon/dto-mapper
使用方法如下:
public function showPetById(ShowPetByIdRequestDto $request) : ShowPetByIdResponseDto { $petId = $request->getPathParameters()->getPetId(); $pet = $this->pets->getById($petId); /** @var OnMoon\DtoMapper\DtoMapper $this->mapper */ return $this->mapper->map($pet, ShowPetByIdResponseDto::class); }
自定义API服务器行为
在请求处理生命周期中,API服务器会发出几个事件,这些事件可以用作替代内置的Symfony Kernel事件,因为前者提供了更多的上下文。这些事件允许您挂钩到API服务器功能并修改其行为。
以下事件可用:
-
OnMoon\OpenApiServerBundle\Event\Server\RequestEvent
RequestEvent事件在请求在OpenAPI模式之前进行验证时发生。此事件允许您在执行验证和处理请求之前修改操作和请求对象。
-
OnMoon\OpenApiServerBundle\Event\Server\RequestDtoEvent
RequestDtoEvent事件在请求内容在表示API请求的DTO对象中反序列化后发生,在将此对象传递给您的RequestHandler实现之前。此事件允许您在将其传递给您的RequestHandler实现之前通过反射修改操作和请求DTO(仅通过反射)。请注意,如果API端点不期望请求体、路径或查询参数,则不会创建ResponseDTO。
-
OnMoon\OpenApiServerBundle\Event\Server\ResponseDtoEvent
ResponseDtoEvent事件在请求处理类执行并返回ResponseDto之后发生,在将此ResponseDto序列化为响应之前。此事件允许您在序列化之前修改ResponseDto内容。这可以用作在Symfony ResponseEvent中修改Response对象的替代方案,避免不必要的响应体json解码/编码。请注意,如果API端点没有响应体,则不会创建ResponseDTO。
-
OnMoon\OpenApiServerBundle\Event\Server\ResponseEvent
ResponseEvent事件在API服务器将响应发送之前发生。此事件允许您在服务器将响应发送到客户端之前修改Response对象。
自定义API服务器代码生成
在API服务器代码生成过程中,代码生成器会发出几个事件,可以用来通过更改OpenAPI规范对象的某些部分或更改代表各种代码定义的对象(如类、属性、方法)来修改生成的代码。
以下事件可用:
-
OnMoon\OpenApiServerBundle\Event\CodeGenerator\ClassGraphReadyEvent
ClassGraphReadyEvent事件在解析所有规范之后,构建要生成的类的图之后发生。
此事件允许您修改:
- 类名、命名空间和路径,
- 属性属性、getter和setter,
- 基础接口和类。
-
OnMoon\OpenApiServerBundle\Event\CodeGenerator\FilesReadyEvent
FilesReadyEvent事件在所有类文件生成之后发生,在将它们写入文件之前。
此事件允许您修改生成的文件内容,例如更改代码风格。