WakeApp / api-platform-bundle
此包已被废弃,不再维护。未建议替代包。
扩展Symfony HttpFoundation,提供封装区域用于与REST API交互
v2.1.0-RC1
2021-07-08 19:10 UTC
Requires
- php: ~7.1||~8.0
- ext-json: *
- psr/log: ^1.0
- symfony/config: ~3.4||~4.0||~5.0
- symfony/dependency-injection: ~3.4||~4.0||~5.0
- symfony/http-foundation: ~3.4||~4.0||~5.0
- symfony/http-kernel: ~3.4||~4.0||~5.0
- symfony/translation-contracts: ^1.1||^2.2
- wakeapp/dto-resolver: ^1.1
- wakeapp/swagger-resolver-bundle: ^0.4.10
Suggests
- symfony/monolog-bundle: Provides possibility for log information into separate channel
- symfony/translation: Provides possibility for translate response codes
Conflicts
- nelmio/api-doc-bundle: <3.0
This package is auto-updated.
Last update: 2021-11-17 15:41:10 UTC
README
介绍
此组件扩展了Symfony的http-foundation组件,允许将API的工作封装在独立的区域中。
通过ParameterBag提供对JSON格式请求内容的处理。组件架构禁止API区域发生致命错误,并始终返回带有相应错误代码的有效响应。完整的错误代码列表可以在ApiException类中找到。
描述API规范必须使用Swagger 2,并采用以下格式之一
- NelmioApiDocBundle.
- swagger-php.
- 使用JSON或YAML(.yml)格式的配置文件。
安装
步骤1:下载组件
打开控制台,转到项目目录,然后执行以下命令下载最适合的稳定版本
composer require wakeapp/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 Linkin\Bundle\SwaggerResolverBundle\LinkinSwaggerResolverBundle(), new Wakeapp\Bundle\ApiPlatformBundle\WakeappApiPlatformBundle(), ]; return $bundles; } // ... }
配置
要开始使用组件,需要创建和定义一个guesser对象,该对象包含确定项目API区域规则。
<?php declare(strict_types=1); namespace App\Guesser\ApiAreaGuesser; use Symfony\Component\HttpFoundation\Request; use Wakeapp\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注册为服务。
# app/config.yml wakeapp_api_platform: api_area_guesser_service: App\Guesser\ApiAreaGuesser
完整参数集
# app/config.yml wakeapp_api_platform: # полное имя класса DTO для стандартизации ответа api_result_dto_class: Wakeapp\Bundle\ApiPlatformBundle\Dto\ApiResultDto # идентификатор сервиса для определения зоны API api_area_guesser_service: App\Guesser\ApiAreaGuesser # идентификатор сервиса для глобального отлавливания ошибок и выдачи специализированных сообщений вместо 500 error_code_guesser_service: Wakeapp\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 Swagger\Annotations as SWG; use Wakeapp\Component\DtoResolver\Dto\DtoResolverTrait; use Wakeapp\Component\DtoResolver\Dto\DtoResolverInterface; /** * @SWG\Definition( * type="object", * description="Profile info", * required={"email", "firstName", "lastName"}, * ) */ class ProfileResultDto implements DtoResolverInterface { use DtoResolverTrait; /** * @var string * * @SWG\Property(description="Profile email", example="test@gmail.com") */ protected $email; /** * @var string * * @SWG\Property(description="User's first name", example="John") */ protected $firstName; /** * @var string * * @SWG\Property(description="User's last name", example="Doe") */ protected $lastName; /** * @return string */ public function getEmail(): string { return $this->email; } /** * @return string */ public function getFirstName(): string { return $this->firstName; } /** * @return string */ 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 Swagger\Annotations as SWG; use Symfony\Component\Routing\Annotation\Route; use Wakeapp\Bundle\ApiPlatformBundle\Factory\ApiDtoFactory; use Wakeapp\Bundle\ApiPlatformBundle\HttpFoundation\ApiResponse; /** * @Route("/api/profile") */ class ProfileController { /** * Returns user profile * * @Route(methods={"GET"}) * * @SWG\Response( * response=ApiResponse::HTTP_OK, * description="Successful result in 'data' offset", * @Model(type=ProfileResultDto::class) * ) * * @param ApiDtoFactory $factory * * @return ApiResponse */ public function getProfile(ApiDtoFactory $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 Swagger\Annotations as SWG; use Wakeapp\Bundle\ApiPlatformBundle\Dto\MagicAwareDtoResolverTrait; use Wakeapp\Component\DtoResolver\Dto\DtoResolverInterface; /** * @SWG\Definition( * type="object", * description="Update profile info", * required={"firstName", "lastName"}, * ) * * @method getEmail(): string */ class UpdateProfileEntryDto implements DtoResolverInterface { use MagicAwareDtoResolverTrait; /** * @var string */ protected $email; /** * @var string * * @SWG\Property(description="User's first name", example="John") */ protected $firstName; /** * @var string * * @SWG\Property(description="User's last name", example="Doe") */ protected $lastName; /** * @return string */ public function getFirstName(): string { return $this->firstName; } /** * @return string */ 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 Swagger\Annotations as SWG; use Symfony\Component\Routing\Annotation\Route; use Wakeapp\Bundle\ApiPlatformBundle\HttpFoundation\ApiResponse; /** * @Route("/api/profile") */ class ProfileController { /** * Update user password * * @Route("/{email}", methods={"PATCH"}) * * @SWG\Parameter(name="email", in="path", type="string", required=true, description="User email") * @SWG\Parameter(name="body", in="body", @Model(type=UpdateProfileEntryDto::class), required=true) * * @param UpdateProfileEntryDto $entryDto * * @return ApiResponse */ public function getProfile(UpdateProfileEntryDto $entryDto): ApiResponse { return new ApiResponse($entryDto); } }
如何描述在注解中的响应封装格式
为了使用注解描述响应封装格式 Wakeapp\Bundle\ApiPlatformBundle\Dto\ApiResultDto
,可以采用以下方法
步骤 1 创建自定义服务器响应
<?php declare(strict_types=1); namespace App\Dto; use Swagger\Annotations as SWG; use Wakeapp\Bundle\ApiPlatformBundle\Dto\ApiResultDto as BaseApiResultDto; use Wakeapp\Component\DtoResolver\Dto\DtoResolverInterface; /** * @SWG\Definition( * type="object", * description="Common API response object template", * required={"code", "message"}, * ) */ class ApiResultDto extends BaseApiResultDto { /** * @var int * * @SWG\Property(description="Response api code", example=0, default=0) */ protected $code = 0; /** * @var string * * @SWG\Property(description="Localized human readable text", example="Successfully") */ protected $message; /** * @var DtoResolverInterface|null * * @SWG\Property(type="object", description="Some specific response data or null") */ protected $data = null; }
步骤 2 在配置中添加
# app/config.yml wakeapp_api_platform: api_result_dto_class: App\Dto\MyApiResultDto
步骤 3 为您的函数添加描述
<?php declare(strict_types=1); use Nelmio\ApiDocBundle\Annotation\Model; use Swagger\Annotations as SWG; use Wakeapp\Bundle\ApiPlatformBundle\HttpFoundation\ApiRequest; use Wakeapp\Bundle\ApiPlatformBundle\HttpFoundation\ApiResponse; use Wakeapp\Bundle\ApiPlatformBundle\Factory\ApiDtoFactory; class ProfileController { /** * ... * * @SWG\Parameter(name="username", in="query", type="string", required=true, description="User login") * @SWG\Response( * response=ApiResponse::HTTP_OK, * description="Successful result in 'data' offset", * @Model(type=ProfileResultDto::class) * ) * @SWG\Response(response="default", @Model(type=ApiResultDto::class), description="Response wrapper") * * @param ApiRequest $apiRequest * @param ApiDtoFactory $factory * * @return ApiResponse */ public function getProfile(ApiRequest $apiRequest, ApiDtoFactory $factory): ApiResponse { return new ApiResponse(); } }