marfatech/api-platform-bundle

扩展 Symfony HttpFoundation,并为与 REST API 的工作提供封装区域

此包的官方存储库似乎已消失,因此该包已被冻结

安装: 376

依赖项: 0

建议者: 0

安全: 0

星标: 0

关注者: 5

分支: 0

开放问题: 0

类型:symfony-bundle

v3.4.0 2022-07-21 10:26 UTC

README

Latest Stable Version Total Downloads

简介

此包扩展了 Symfony 的 http-foundation 组件,允许将 API 的工作分离成一个独立的封装区域。

通过 ParameterBag 提供对请求内容的 JSON 格式处理。包的架构不允许 API 区域出现致命错误,并始终返回包含相应错误代码的有效响应。错误代码的完整列表可以在 ApiException 类中以常量的形式找到。

建议使用 OpenApi 3swagger-resolver-bundle 一起,在以下格式中选择一种来描述 API 规范:

安装

步骤 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();
    }
}

许可证

license