Skip to content
This repository was archived by the owner on Nov 6, 2021. It is now read-only.

Repository files navigation

Api Platform Bundle

Latest Stable VersionTotal Downloads

Введение

Бандл расширяет компонет Symfony http-foundation позволя выделить работу с API в отдельную инкапсулированную зону.

Предоставляется работа с контентом запроса в формате JSON посредством ParameterBag. Архитектура бандла не допускает фатального падения в зоне API и всегда возвращает валидный ответ с соответствующем кодом ошибки. Полный список кодов ошибок доступен в виде констант в классе ApiException.

Для описания спецификации API обязательно использование Swagger 2 в одном из форматов:

Установка

Шаг 1: Загрузка бандла

Откройте консоль и, перейдя в директорию проекта, выполните следующую команду для загрузки наиболее подходящей стабильной версии этого бандла:

 composer require wakeapp/api-platform-bundle

Эта команда подразумевает что Composer установлен и доступен глобально.

Шаг 2: Подключение бандла

После включите бандл добавив его в список зарегистрированных бандлов в app/AppKernel.php файл вашего проекта:

<?phpdeclare(strict_types=1);
// app/AppKernel.phpclass AppKernel extends Kernel
{
// ...publicfunctionregisterBundles()
{
$bundles = [
// ...newLinkin\Bundle\SwaggerResolverBundle\LinkinSwaggerResolverBundle(),
newWakeapp\Bundle\ApiPlatformBundle\WakeappApiPlatformBundle(),
];
return$bundles;
}
// ...
}

Конфигурация

Чтобы начать использовать бандл требуется определить создать и определить guesser - объект содержащий правила определения зоны API вашего проекта.

<?phpdeclare(strict_types=1);
namespaceApp\Guesser\ApiAreaGuesser;
useSymfony\Component\HttpFoundation\Request;
useWakeapp\Bundle\ApiPlatformBundle\Guesser\ApiAreaGuesserInterface;
class ApiAreaGuesser implements ApiAreaGuesserInterface
{
/** * {@inheritDoc} */publicfunctiongetApiVersion(Request$request): ?int
{
$apiVersionMatch = [];
preg_match('/^\/v([\d]+)\//i', $request->getPathInfo(), $apiVersionMatch);
if (empty($apiVersionMatch)) {
returnnull;
}
$apiVersion = (int) end($apiVersionMatch);
return$apiVersion;
}
/** * {@inheritdoc} */publicfunctionisApiRequest(Request$request): bool
{
returnstrpos($request->getPathInfo(), '/api') === 0;
}
}

Примечание: Если вы не используете autowire то вам необходимо зарегистрировать ApiAreaGuesser как сервис.

# app/config.ymlwakeapp_api_platform:
api_area_guesser_service: App\Guesser\ApiAreaGuesser

Полный набор параметров

# app/config.ymlwakeapp_api_platform:
# полное имя класса DTO для стандартизации ответаapi_result_dto_class: Wakeapp\Bundle\ApiPlatformBundle\Dto\ApiResultDto# идентификатор сервиса для определения зоны APIapi_area_guesser_service: App\Guesser\ApiAreaGuesser# идентификатор сервиса для глобального отлавливания ошибок и выдачи специализированных сообщений вместо 500error_code_guesser_service: Wakeapp\Bundle\ApiPlatformBundle\Guesser\ApiErrorCodeGuesser# Минимально допустимая версия API.minimal_api_version: 1# флаг для отладки ошибок - если установлен в true - ответ ошибки содержит trace.response_debug: false

Использование

Использование функционала бандла начинается с создание контроллера и первого метода в указанной зоне API. В качестве примера рассмотрим возвращение простейшего профиля пользователя.

Для начала нам необходимо создать DTO возвращаемых данных:

<?phpdeclare(strict_types=1);
namespaceApp\Dto;
useSwagger\AnnotationsasSWG;
useWakeapp\Component\DtoResolver\Dto\DtoResolverTrait;
useWakeapp\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 */publicfunctiongetEmail(): string
{
return$this->email;
}
/** * @return string */publicfunctiongetFirstName(): string
{
return$this->firstName;
}
/** * @return string */publicfunctiongetLastName(): string
{
return$this->lastName;
}
}

Теперь добавим контроллер с соответствующим методом. Примечание: в качестве примера реализации используется подключение NelmioApiDocBundle.

<?phpdeclare(strict_types=1);
namespaceApp\Controller;
useApp\Dto\ProfileResultDto;
useNelmio\ApiDocBundle\Annotation\Model;
useSwagger\AnnotationsasSWG;
useSymfony\Component\Routing\Annotation\Route;
useWakeapp\Bundle\ApiPlatformBundle\Factory\ApiDtoFactory;
useWakeapp\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 */publicfunctiongetProfile(ApiDtoFactory$factory): ApiResponse
{
// обработка данных$resultDto = $factory->createApiDto(ProfileResultDto::class, [
'email' => 'test-user@mail.ru',
'firstName' => 'Test',
'lastName' => 'User',
]);
returnnewApiResponse($resultDto);
}
}

Дополнительно

Как комбинировать body параметры с query и/или path

Объект на DTO:

<?phpdeclare(strict_types=1);
namespaceApp\Dto;
useSwagger\AnnotationsasSWG;
useWakeapp\Bundle\ApiPlatformBundle\Dto\MagicAwareDtoResolverTrait;
useWakeapp\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 */publicfunctiongetFirstName(): string
{
return$this->firstName;
}
/** * @return string */publicfunctiongetLastName(): string
{
return$this->lastName;
}
}

Контроллер:

<?phpdeclare(strict_types=1);
namespaceApp\Controller;
useApp\Dto\UpdateProfileEntryDto;
useNelmio\ApiDocBundle\Annotation\Model;
useSwagger\AnnotationsasSWG;
useSymfony\Component\Routing\Annotation\Route;
useWakeapp\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 */publicfunctiongetProfile(UpdateProfileEntryDto$entryDto): ApiResponse
{
returnnewApiResponse($entryDto);
}
}

Как описать в формат обертки ответа в аннотациях

Чтобы описать формат обертки ответа Wakeapp\Bundle\ApiPlatformBundle\Dto\ApiResultDto при помощи аннотаций можно использовать следующий подход:

Шаг 1 Создайте собственный ответ сервера:

<?phpdeclare(strict_types=1);
namespaceApp\Dto;
useSwagger\AnnotationsasSWG;
useWakeapp\Bundle\ApiPlatformBundle\Dto\ApiResultDtoasBaseApiResultDto;
useWakeapp\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.ymlwakeapp_api_platform:
api_result_dto_class: App\Dto\MyApiResultDto

Шаг 3 Добавьте описание к вашему методу:

<?phpdeclare(strict_types=1);
useNelmio\ApiDocBundle\Annotation\Model;
useSwagger\AnnotationsasSWG;
useWakeapp\Bundle\ApiPlatformBundle\HttpFoundation\ApiRequest;
useWakeapp\Bundle\ApiPlatformBundle\HttpFoundation\ApiResponse;
useWakeapp\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 */publicfunctiongetProfile(ApiRequest$apiRequest, ApiDtoFactory$factory): ApiResponse
{
returnnewApiResponse();
}
}

Лицензия

license

About

Extends Symfony HttpFoundation and provides encapsulated area for work with REST API

Topics

Resources

Stars

8 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages