marfatech / api-platform-bundle
扩展 Symfony HttpFoundation,并为与 REST API 的工作提供封装区域
此包的官方存储库似乎已消失,因此该包已被冻结
Requires
- php: ~8.0
- ext-json: *
- marfatech/dto-resolver: ^2.0
- psr/log: ^1.0
- symfony/config: ~4.4||~5.4||~6.0
- symfony/dependency-injection: ~4.4||~5.4||~6.0
- symfony/http-foundation: ~4.4||~5.4||~6.0
- symfony/http-kernel: ~4.4||~5.4||~6.0
- symfony/options-resolver: ~4.4||~5.4||~6.0
- symfony/translation-contracts: ^1.1||^2.2||^3.0
Requires (Dev)
- phpunit/phpunit: ^9.5
- roave/security-advisories: dev-latest
- symfony/flex: ^2.2
- symfony/monolog-bundle: ^3.7
- symfony/phpunit-bridge: ~4.4||~5.4||~6.0
- symfony/translation: ~4.4||~5.4||^6.0
- symfony/validator: ~4.4||~5.4||^6.0
- symfony/yaml: ~4.4||~5.4||~6.0
Suggests
- marfatech/swagger-resolver-bundle: Provides possibility to resolve DTO by swagger definition
- symfony/monolog-bundle: Provides possibility for log information into separate channel
- symfony/translation: Provides possibility for translate response codes
- symfony/validator: Provides possibility for catch constraint validation
Conflicts
This package is auto-updated.
Last update: 2024-02-15 13:27:56 UTC
README
简介
此包扩展了 Symfony 的 http-foundation 组件,允许将 API 的工作分离成一个独立的封装区域。
通过 ParameterBag
提供对请求内容的 JSON
格式处理。包的架构不允许 API 区域出现致命错误,并始终返回包含相应错误代码的有效响应。错误代码的完整列表可以在 ApiException 类中以常量的形式找到。
建议使用 OpenApi 3 与 swagger-resolver-bundle 一起,在以下格式中选择一种来描述 API 规范:
- NelmioApiDocBundle.
- swagger-php.
- 可以使用
json
或yaml
(yml
)格式的配置文件。
安装
步骤 1:下载包
打开控制台,切换到项目目录,然后执行以下命令下载此包的最稳定版本
composer require marfatech/api-platform-bundle
此命令假定您已安装并全局可用 Composer。
步骤 2:连接包
之后,将包添加到项目中 app/AppKernel.php
文件中注册的包列表中
<?php declare(strict_types=1); // app/AppKernel.php class AppKernel extends Kernel { // ... public function registerBundles() { $bundles = [ // ... new MarfaTech\Bundle\ApiPlatformBundle\MarfaTechApiPlatformBundle(), ]; return $bundles; } // ... }
配置
要开始使用此包,需要创建并定义一个 guesser
对象,该对象包含用于确定项目 API 区域的规则。
<?php declare(strict_types=1); namespace App\Guesser\ApiAreaGuesser; use Symfony\Component\HttpFoundation\Request; use MarfaTech\Bundle\ApiPlatformBundle\Guesser\ApiAreaGuesserInterface; class ApiAreaGuesser implements ApiAreaGuesserInterface { /** * {@inheritDoc} */ public function getApiVersion(Request $request): ?int { $apiVersionMatch = []; preg_match('/^\/v([\d]+)\//i', $request->getPathInfo(), $apiVersionMatch); if (empty($apiVersionMatch)) { return null; } $apiVersion = (int) end($apiVersionMatch); return $apiVersion; } /** * {@inheritdoc} */ public function isApiRequest(Request $request): bool { return strpos($request->getPathInfo(), '/api') === 0; } }
注意:如果您不使用 autowire
,则需要将 ApiAreaGuesser
注册为服务。
# config/packages/marfa_tech_api_platform.yaml marfa_tech_api_platform: api_area_guesser_service: App\Guesser\ApiAreaGuesser
完整的参数集
# config/packages/marfa_tech_api_platform.yaml marfa_tech_api_platform: # полное имя класса DTO для стандартизации ответа api_result_dto_class: MarfaTech\Bundle\ApiPlatformBundle\Dto\ApiResultDto # идентификатор сервиса для определения зоны API api_area_guesser_service: App\Guesser\ApiAreaGuesser # идентификатор сервиса для глобального отлавливания ошибок и выдачи специализированных сообщений вместо 500 error_code_guesser_service: MarfaTech\Bundle\ApiPlatformBundle\Guesser\ApiErrorCodeGuesser # Минимально допустимая версия API. minimal_api_version: 1 # флаг для отладки ошибок - если установлен в true - ответ ошибки содержит trace. response_debug: false
使用
使用此包的功能从创建控制器和指定区域 API 中的第一个方法开始。以下示例将展示如何返回最简单的用户资料。
首先,我们需要创建返回数据的 DTO。
<?php declare(strict_types=1); namespace App\Dto; use OpenApi\Annotations as OA; use MarfaTech\Component\DtoResolver\Dto\DtoResolverTrait; use MarfaTech\Component\DtoResolver\Dto\DtoResolverInterface; /** * @OA\Schema( * type="object", * description="Profile info", * required={"email", "firstName", "lastName"}, * ) */ class ProfileResultDto implements DtoResolverInterface { use DtoResolverTrait; /** * @OA\Property(description="Profile email", example="test@gmail.com") */ protected string $email; /** * @OA\Property(description="User's first name", example="John") */ protected string $firstName; /** * @OA\Property(description="User's last name", example="Doe") */ protected string $lastName; public function getEmail(): string { return $this->email; } public function getFirstName(): string { return $this->firstName; } public function getLastName(): string { return $this->lastName; } }
现在,我们将添加一个控制器和相应的方法。 注意:以下示例使用了 NelmioApiDocBundle 的实现方式。
<?php declare(strict_types=1); namespace App\Controller; use App\Dto\ProfileResultDto; use Nelmio\ApiDocBundle\Annotation\Model; use OpenApi\Annotations as OA; use Symfony\Component\Routing\Annotation\Route; use MarfaTech\Bundle\ApiPlatformBundle\Factory\ApiDtoFactory; use MarfaTech\Bundle\ApiPlatformBundle\HttpFoundation\ApiResponse; use MarfaTech\Bundle\ApiPlatformBundle\Factory\ApiDtoResolverFactoryInterface; /** * @Route("/api/profile") */ class ProfileController { /** * Returns user profile * * @Route(methods={"GET"}) * * @OA\Response( * response=ApiResponse::HTTP_OK, * description="Successful result in 'data' offset", * @Model(type=ProfileResultDto::class), * * ) */ public function getProfile(ApiDtoResolverFactoryInterface $factory): ApiResponse { // обработка данных $resultDto = $factory->createApiDto(ProfileResultDto::class, [ 'email' => 'test-user@mail.ru', 'firstName' => 'Test', 'lastName' => 'User', ]); return new ApiResponse($resultDto); } }
其他
如何合并 body 参数与 query 和/或 path
DTO 对象
<?php declare(strict_types=1); namespace App\Dto; use OpenApi\Annotations as OA; use MarfaTech\Bundle\ApiPlatformBundle\Dto\MagicAwareDtoResolverTrait; use MarfaTech\Component\DtoResolver\Dto\DtoResolverInterface; /** * @OA\Schema( * type="object", * description="Update profile info", * required={"firstName", "lastName"}, * ) * * @method getEmail(): string */ class UpdateProfileEntryDto implements DtoResolverInterface { use MagicAwareDtoResolverTrait; protected string $email; /** * @OA\Property(description="User's first name", example="John") */ protected string $firstName; /** * @OA\Property(description="User's last name", example="Doe") */ protected string $lastName; public function getFirstName(): string { return $this->firstName; } public function getLastName(): string { return $this->lastName; } }
控制器
<?php declare(strict_types=1); namespace App\Controller; use App\Dto\UpdateProfileEntryDto; use Nelmio\ApiDocBundle\Annotation\Model; use OpenApi\Annotations as OA; use Symfony\Component\Routing\Annotation\Route; use MarfaTech\Bundle\ApiPlatformBundle\HttpFoundation\ApiResponse; /** * @Route("/api/profile") */ class ProfileController { /** * Update user password * * @Route("/{email}", methods={"PATCH"}) * * @OA\Parameter(name="email", in="path", @OA\Schema(type="string"), required=true, description="User email") * @OA\RequestBody(required=true, @Model(type=UpdateProfileEntryDto::class)) */ public function getProfile(UpdateProfileEntryDto $entryDto): ApiResponse { return new ApiResponse($entryDto); } }
如何在注解中描述响应包装体的格式
为了使用注解描述响应包装体格式 MarfaTech\Bundle\ApiPlatformBundle\Dto\ApiResultDto
,可以采用以下方法
步骤 1 创建自定义服务器响应
<?php declare(strict_types=1); namespace App\Dto; use OpenApi\Annotations as OA; use MarfaTech\Bundle\ApiPlatformBundle\Dto\ApiResultDto as BaseApiResultDto; use MarfaTech\Component\DtoResolver\Dto\DtoResolverInterface; /** * @OA\Schema( * type="object", * description="Common API response object template", * required={"code", "message"}, * ) */ class ApiResultDto extends BaseApiResultDto { /** * @var int * * @OA\Property(description="Response api code", example=0, default=0) */ protected $code = 0; /** * @var string * * @OA\Property(description="Localized human readable text", example="Successfully") */ protected $message; /** * @var DtoResolverInterface|null * * @OA\Property(type="object", description="Some specific response data or null") */ protected $data = null; }
步骤 2 在配置中添加
# config/packages/marfa_tech_api_platform.yaml marfa_tech_api_platform: api_result_dto_class: App\Dto\MyApiResultDto
步骤 3 为您的函数添加描述
<?php declare(strict_types=1); use Nelmio\ApiDocBundle\Annotation\Model; use OpenApi\Annotations as OA; use MarfaTech\Bundle\ApiPlatformBundle\HttpFoundation\ApiRequest; use MarfaTech\Bundle\ApiPlatformBundle\HttpFoundation\ApiResponse; use MarfaTech\Bundle\ApiPlatformBundle\Factory\ApiDtoFactory; use MarfaTech\Bundle\ApiPlatformBundle\Factory\ApiDtoResolverFactoryInterface; class ProfileController { /** * ... * * @OA\Parameter(name="username", in="query", @OA\Schema(type="string"), required=true, description="User login") * @OA\Response( * response=ApiResponse::HTTP_OK, * description="Successful result in 'data' offset", * @Model(type=ProfileResultDto::class), * ) * @OA\Response(response="default", @Model(type=ApiResultDto::class), description="Response wrapper") */ public function getProfile(ApiRequest $apiRequest, ApiDtoResolverFactoryInterface $factory): ApiResponse { return new ApiResponse(); } }