donurks / phrest
一个支持swagger和hateoas的REST API库。
Requires
- php: ^7.1
- justinrainbow/json-schema: 5.2.1
- monolog/monolog: 1.23.0
- willdurand/hateoas: 2.11.0
- zendframework/zend-cache: 2.7.2
- zendframework/zend-config-aggregator: 1.0.0
- zendframework/zend-expressive: 2.0.3
- zendframework/zend-expressive-fastroute: 2.0.0
- zendframework/zend-expressive-helpers: 4.0.0
- zendframework/zend-servicemanager: 3.3.0
- zircote/swagger-php: 2.0.10
Requires (Dev)
- phpunit/phpunit: 6.3.0
This package is not auto-updated.
Last update: 2024-09-28 02:03:47 UTC
README
phrest
A PHP框架,用于构建支持JSON和Swagger的RESTful API。Phrest会自动扫描您的代码以查找swagger或HATEOAS注解。如果需要,Phrest可以使用扫描到的swagger注解进行请求数据验证(见AbstractSwaggerValidatorAction)。
特性
- 注解中的Swagger 2.0定义(zircote/swagger-php)
- 注解中的HATEOAS响应定义(willdurand/Hateoas)
- 使用swagger数据对请求数据进行验证(justinrainbow/json-schema)
- PSR-3日志记录(Seldaek/monolog)
- PSR-7 HTTP消息
- PSR-11容器
- PSR-15中间件(可扩展)
- API消费者错误代码
- 统一异常处理HTTP状态代码
要求
- PHP 7.1
- 理解zircote/swagger-php注解
- 理解willdurand/Hateoas注解
安装(使用Composer)
命令行
composer require donurks/phrest
public/index.php
<?php chdir(dirname(__DIR__)); require_once "vendor/autoload.php"; \Phrest\Application::run('phrest-example');
快速入门(使用donurks/phrest-skeleton)
composer create-project donurks/phrest-skeleton
\Phrest\Application::run参数
配置
默认情况下,phrest会查看您的config/
目录,并按以下顺序加载和合并所有配置文件
- global.php
- *.global.php
- local.php
- *.local.php
<?php // Config files should return arrays return [ 'my-config-entry' => 'my-config-value' ];
您可以通过为\Phrest\Application::run
提供第二个参数来使用自己的配置文件加载模式(glob)。
<?php \Phrest\Application::run('phrest-example', 'my_own_config_dir/just_one_config_file.php');
配置
对于phrest配置,在\Phrest\Application
上有预定义的类常量,您可以在配置数组中用作配置条目。
<?php return [ \Phrest\Application::CONFIG_ENABLE_CACHE => true ];
用户配置
您可以通过\Phrest\Application::USER_CONFIG
常量在容器中访问整个配置。
<?php return [ 'my-own-config' => 'some-value', \Phrest\Application::CONFIG_DEPENDENCIES => [ 'factories' => [ \Application\Action\SomeAction::class => function (\Interop\Container\ContainerInterface $container) { $userConfig = $container->get(\Phrest\Application::USER_CONFIG); $myOwnConfigValue = $userConfig['my-own-config']; // ... }, ] ], ];
服务
Phrest为您提供了几个服务。您可以在zend-servicemanager工厂容器中访问它们。
<?php return [ \Phrest\Application::CONFIG_DEPENDENCIES => [ 'factories' => [ \Application\Action\SomeAction::class => function (\Interop\Container\ContainerInterface $container) { return new \Application\Action\SomeAction( $container->get(\Phrest\Application::SERVICE_LOGGER) ); }, ] ], ];
操作
Phrest为您提供了几个操作。您可以通过简单地将它们绑定到路径来使用它们。
<?php return [ \Phrest\Application::CONFIG_ROUTES => [ // call http://your-host/swagger to see your swagger file 'swagger' => \Phrest\Application::createRoute( '/swagger', \Phrest\Application::ACTION_SWAGGER ), ], ];
路由
路由是路径和操作之间的连接。使用\Phrest\Application::CONFIG_ROUTES
配置添加路由。还有一个静态方法\Phrest\Application::createRoute()
,用于创建路由条目。
数组键用于命名路由。路由名称用于HATEOAS响应生成器中的链接生成。
您还可以提供操作ID的映射(见AbstractSwaggerValidatorAction)。
<?php
// your config file
return [
\Phrest\Application::CONFIG_ROUTES => [
'the-name-of-your-route' => \Phrest\Application::createRoute(
'/the-path-of-your-route',
// Your action - must be refer to a service in your CONFIG_DEPENDENCIES
\YourAction::class,
[
// AbstractSwaggerValidatorAction will now use "someOperationId" instead of "get.the-name-of-your-route"
'get' => 'someOperationId'
]
),
],
];
抽象操作
您可以通过实现\Interop\Http\ServerMiddleware\MiddlewareInterface
来编写自己的操作。或者您可以使用phrest提供的抽象操作。
抽象Action
如果您只想将HTTP方法映射到操作方法,请使用此抽象操作。
扩展\Phrest\API\AbstractAction
类并按需覆盖方法。如果phrest收到您的操作未提供的方法的请求,phrest将自动处理错误响应。
<?php class Test extends \Phrest\API\AbstractAction { public function get(\Psr\Http\Message\ServerRequestInterface $request): \Psr\Http\Message\ResponseInterface { return new \Zend\Diactoros\Response\JsonResponse(['name' => 'some name']); } }
AbstractSwaggerValidatorAction
使用此抽象动作,如果要让 phrest 根据Swagger注解验证您的请求。
Phrest 将使用当前路由名称来验证您在Swagger注解中定义的所有请求参数。默认情况下,phrest 将使用具有以下模式的 operationId:"method.route-name" ("get.name-of-your-route")。
您可以覆盖每个方法的 operationId(参见 路由)。
路由中定义的 operationId 必须与 Swagger 注解中的 operationId 匹配。
如果验证失败,phrest 将自动处理错误响应。
扩展 \Phrest\API\AbstractSwaggerValidatorAction
类并根据需要覆盖方法。如果 phrest 收到您动作未提供的请求方法,将抛出 \Phrest\Http\Exception
,导致返回 http 状态 405 的错误模型响应(参见 异常)。
使用 \Phrest\API\RequestSwaggerData
对象来访问您的请求参数。有关详细信息,请参阅 请求 Swagger 验证器。
<?php // your config file return [ \Phrest\Application::CONFIG_ROUTES => [ // The route name "someRouteName" matches operationId in the swagger annotations 'someRouteName' => \Phrest\Application::createRoute( '/some-path', \SomeAction::class ), ], ];
<?php // your action class SomeAction extends \Phrest\API\AbstractSwaggerValidatorAction { /** * @SWG\Get( * path="/some-path", * operationId="someRouteName", * @SWG\Parameter( * name="id", * in="query", * type="number" * ), * @SWG\Response(response="200", description="Success") * ) * * @param \Phrest\API\RequestSwaggerData $data * @return \Psr\Http\Message\ResponseInterface */ public function get(\Phrest\API\RequestSwaggerData $data): \Psr\Http\Message\ResponseInterface { return new \Zend\Diactoros\Response\JsonResponse( ['id' => $data->getQueryValues()['id']] ); } }
请求 Swagger 验证器
您可以使用请求 Swagger 验证器来验证您的请求参数与 Swagger 操作。只需提供您的请求对象和 Swagger operationId。Phrest 将使用由 operation Id 链接的操作中提供的所有参数定义。
您可以使用服务 \Phrest\Application::SERVICE_REQUEST_SWAGGER_VALIDATOR
将请求 Swagger 验证器注入到您的类中。
<?php // your config file return [ \Phrest\Application::CONFIG_DEPENDENCIES => [ 'factories' => [ \SomeAction::class => function (\Interop\Container\ContainerInterface $container) { return new \SomeAction( $container->get(\Phrest\Application::SERVICE_REQUEST_SWAGGER_VALIDATOR) ); }, ] ], ];
您还可以实现 \Phrest\API\RequestSwaggerValidatorAwareInterface
并使用 \Phrest\API\RequestSwaggerValidatorAwareTrait
。Phrest 将自动将请求 Swagger 验证器注入到您的类中,并填充一个 requestSwaggerValidator
属性。
<?php // your action class SomeAction extends \Phrest\API\AbstractAction implements \Phrest\API\RequestSwaggerValidatorAwareInterface { use \Phrest\API\RequestSwaggerValidatorAwareTrait; public function get(\Psr\Http\Message\ServerRequestInterface $request): \Psr\Http\Message\ResponseInterface { $data = $this->requestSwaggerValidator->validate($request, 'someOperationId'); return new \Zend\Diactoros\Response\EmptyResponse(); } }
或者,直接使用 AbstractSwaggerValidatorAction,phrest 将负责获取正确的 operationId。
validate 方法接受两个参数:请求对象和 operationId。
Phrest 将在您的 Swagger 中查找给定的 operationId。如果没有为此 ID 定义的此操作,如果没有捕获,则 phrest 将抛出 \Phrest\Exception
,导致返回 http 状态 500 的响应。如果验证失败,如果没有捕获,则 phrest 将抛出 \Phrest\Http\Exception
,导致返回 http 状态 400 的响应,其中包含错误模型。
如果验证成功,validate 方法将返回一个 \Phrest\API\RequestSwaggerData
对象。
\Phrest\API\RequestSwaggerData
对象包含所有经过验证的参数,填充了默认值(如果定义)和正确的数据类型(如 Swagger 注解中定义)。
有关 swagger-php 的详细信息,请参阅 zircote/swagger-php。
有关 Swagger 的详细信息,请参阅 OpenAPI 规范 2.0。
HATEOAS 响应生成器
HATEOAS 响应生成器将使用注解(willdurand/Hateoas)从您的对象生成 JSON 响应。
您可以使用服务 \Phrest\Application::SERVICE_HATEOAS_RESPONSE_GENERATOR
将 HATEOAS 响应生成器注入到您的类中。
<?php // your config file return [ \Phrest\Application::CONFIG_DEPENDENCIES => [ 'factories' => [ \SomeAction::class => function (\Interop\Container\ContainerInterface $container) { return new \SomeAction( $container->get(\Phrest\Application::SERVICE_HATEOAS_RESPONSE_GENERATOR) ); }, ] ], ];
您还可以实现 \Phrest\API\HateoasResponseGeneratorAwareInterface
并使用 \Phrest\API\HateoasResponseGeneratorAwareTrait
。Phrest 将自动将响应生成器注入到您的类中,并填充一个 generateHateoasResponse
方法。
<?php // your action class SomeAction extends \Phrest\API\AbstractAction implements \Phrest\API\HateoasResponseGeneratorAwareInterface { use \Phrest\API\HateoasResponseGeneratorAwareTrait; public function get(\Psr\Http\Message\ServerRequestInterface $request): \Psr\Http\Message\ResponseInterface { $user = new User( 453, 'Bruce', 'Wayne' ); return $this->generateHateoasResponse($user); } }
generateHateoasResponse
方法接受您的对象,可选的 http 状态码和一个头数组。
您可以使用 HATEOAS 路由与关联注解一起生成链接。只需传递路由名称(参见 路由)。您还可以传递命名路径参数以生成 URL。
<?php // your config file return [ \Phrest\Application::CONFIG_ROUTES => [ 'your-route' => \Phrest\Application::createRoute( '/users/{userId}', \YourAction::class ), ], ];
<?php /** * @Hateoas\Configuration\Annotation\Relation( * "self", * href = @Hateoas\Configuration\Annotation\Route( * "your-route", * parameters = { "userId" = "expr(object.getId())" }, * absolute = true * ) * ) */ class User { private $id; private $first_name; private $last_name; public function __construct($id, $first_name, $last_name) { $this->id = $id; $this->first_name = $first_name; $this->last_name = $last_name; } public function getId() { return $this->id; } }
生成的输出现在应如下所示
{ "id": 453, "first_name": "Bruce", "last_name": "Wayne", "_links": { "self": { "href": "https:///users/453" } } }
有关 willdurand/Hateoas 的详细信息,请参阅 willdurand/Hateoas。
日志记录
您可以使用服务 \Phrest\Application::SERVICE_LOGGER
将记录器注入到您的类中。
<?php // your config file return [ \Phrest\Application::CONFIG_DEPENDENCIES => [ 'factories' => [ \SomeAction::class => function (\Interop\Container\ContainerInterface $container) { return new \SomeAction( $container->get(\Phrest\Application::SERVICE_LOGGER) ); }, ] ], ];
您还可以实现 \Psr\Log\LoggerAwareInterface
并使用 \Psr\Log\LoggerAwareTrait
。Phrest 将自动将日志记录器注入到您的类中,并填充一个 logger
属性。
<?php // your action class SomeAction extends \Phrest\API\AbstractAction implements \Psr\Log\LoggerAwareInterface { use \Psr\Log\LoggerAwareTrait; public function get(\Psr\Http\Message\ServerRequestInterface $request): \Psr\Http\Message\ResponseInterface { $this->logger->info('a log message'); return new \Zend\Diactoros\Response\EmptyResponse(); } }
有关处理器和处理器详情,请参阅 Monolog。
异常
Phrest 对于每个未处理的异常,将生成带有 HTTP 状态码 500 的响应。
除了 \Phrest\Http\Exception
之外。如果没有捕获,Phrest 将生成带有正确 HTTP 状态码和错误模型体的响应。
每个 \Phrest\Http\Exception
都需要一个 HTTP 状态码和一个包含错误条目的错误模型。
在 \Phrest\API\Error
和 \Phrest\API\ErrorEntry
上的错误代码应从 \Phrest\API\ErrorCodes
或您自己的错误代码类中使用(见 错误代码)。
<?php // all alone throw new \Phrest\Http\Exception( 400, new \Phrest\API\Error( 1, 'Request parameter validation error', new \Phrest\API\ErrorEntry( 2, '{query}/id', 'Value must be a number, string given', 'is_number' ) ) ); // with short hand method throw \Phrest\Http\Exception::Unauthorized( new \Phrest\API\Error( 1, 'Request parameter validation error', new \Phrest\API\ErrorEntry( 2, '{query}/id', 'Value must be a number, string given', 'is_number' ) ) ); // with error codes class throw \Phrest\Http\Exception::Unauthorized( new \Phrest\API\Error( \Phrest\API\ErrorCodes::REQUEST_PARAMETER_VALIDATION, 'Request parameter validation error', new \Phrest\API\ErrorEntry( \Phrest\API\ErrorCodes::REQUEST_VALIDATION_TYPE, '{query}/id', 'Value must be a number, string given', 'is_number' ) ) );
错误代码
您可以使用 phrest 错误代码操作发布您的错误代码以供 API 消费者使用。
<?php // your configuration file return [ \Phrest\Application::CONFIG_ROUTES => [ 'error_codes' => \Phrest\Application::createRoute( '/your/path/to/error_codes', \Phrest\Application::ACTION_ERROR_CODES ), ], ];
现在调用 https:///your/path/to/error_codes 以查看您的错误代码。
使用自己的错误代码
您可以向 Phrest 指定要使用的错误代码类。只需将您的 ErrorCodes 类注册到 \Phrest\Application::CONFIG_ERROR_CODES
下。Phrest 使用从 0 到 1000 的错误代码。为了避免冲突,您应该使用 LAST_PHREST_ERROR_CODE
作为您自己的错误代码的基础。
<?php namespace Application; class ErrorCodes extends \Phrest\API\ErrorCodes { const MY_OWN_ERROR = self::LAST_PHREST_ERROR_CODE + 1; const MY_OWN_ERROR_2 = self::LAST_PHREST_ERROR_CODE + 2; }
<?php // your configuration file return [ \Phrest\Application::CONFIG_ERROR_CODES => \Application\ErrorCodes::class, \Phrest\Application::CONFIG_DEPENDENCIES => [ 'invokables' => [ \Application\ErrorCodes::class => \Application\ErrorCodes::class, ] ], ];
现在调用 https:///your/path/to/error_codes,您应该看到 Phrest 错误代码和您自己的错误代码。
待办事项
- CallableUrlGenerator
- 缺少参数的 URL 生成导致无效 URL(hateoas 链接参数)
- 验证头与 swagger consumes 值的对比
- ReadMe(一些链接不起作用)
- 单元测试
- 添加 OpenAPI Spec 3.0 支持(一旦 zircote/swagger-php 3.0 发布)
- HAL 链接(OpenAPI Spec 3.0 的一部分)
- 解决代码中的待办事项
- 检查缓存速度和需求(文件系统访问成本与可缓存过程成本)
- 细粒度的用户缓存配置?(缓存 swagger:是,缓存错误代码:否,...)
- 在 zend-cache 2.8.0 发布后注入可注入的 PSR-16 (\Psr\SimpleCache\CacheInterface) 缓存适配器 2.8.0