chimera / routing
一组可重用的PSR-15组件,将Chimera连接到任何框架
Requires
- php: ^7.4 || ^8.0
- chimera/foundation: ^0.4
- fig/http-message-util: ^1.1
- lcobucci/content-negotiation-middleware: ^3.0
- middlewares/negotiation: ^2.0
- psr/http-factory: ^1.0
- psr/http-message: ^1.0
- psr/http-server-handler: ^1.0
- psr/http-server-middleware: ^1.0
Requires (Dev)
- infection/infection: ^0.21
- laminas/laminas-diactoros: ^2.5
- lcobucci/coding-standard: ^6.0
- phpstan/extension-installer: ^1.1
- phpstan/phpstan: ^0.12
- phpstan/phpstan-deprecation-rules: ^0.12
- phpstan/phpstan-phpunit: ^0.12
- phpstan/phpstan-strict-rules: ^0.12
- phpunit/phpunit: ^9.5
- 1.0.x-dev
- 0.4.x-dev
- 0.4.0
- 0.3.x-dev
- 0.3.4
- 0.3.3
- 0.3.2
- 0.3.1
- 0.3.0
- 0.2.0
- 0.1.0
- dev-renovate/phpstan-packages
- dev-renovate/test-packages
- dev-renovate/all-minor-patch
- dev-renovate/codecov-codecov-action-4.x
- dev-renovate/actions-cache-4.x
- dev-renovate/major-test-packages
- dev-renovate/psr-http-message-2.x
- dev-renovate/lcobucci-coding-standard-11.x
- dev-renovate/laminas-laminas-diactoros-3.x
- dev-dependabot/composer/laminas/laminas-diactoros-2.24.2
- dev-renovate/lock-file-maintenance
This package is auto-updated.
Last update: 2024-09-20 14:22:48 UTC
README
术语Chimera(/kɪˈmɪərə/ 或 /kaɪˈmɪərə/)用来描述任何由多种动物部分组成的神话或虚构动物,或用来描述由非常不同部分组成或被认为是异想天开、不可信或耀眼的事物。
PHP社区中有许多令人惊叹的库,随着PSRs的创建和采用,我们不一定需要依赖全栈框架来创建复杂且设计良好的软件。选择要使用的组件并将它们组合起来有时可能会有些挑战。
这些包的目的是使这变得更容易(而不牺牲质量),让您能够专注于软件的行为。
这个特定的包提供了PSR-15 中间件和可重用的 请求处理器,帮助您使用HTTP作为网络机制来公开命令和查询处理器。
安装
您可能不会直接依赖这个包,但它可以在 Packagist 上找到,并且可以使用 Composer 安装
composer require chimera/routing
PHP配置
为了确保我们处理的是正确的数据,我们使用assert()
,这是PHP中一个非常有趣的功能,但不太常用。关于assert()
的好之处在于我们可以(也应该)在生产模式下禁用它,这样我们就没有无用的语句。
因此,对于生产模式,我们建议您在您的php.ini
中将zend.assertions
设置为-1
。对于开发,您应该将zend.assertions
保留为1
并将assert.exception
设置为1
,这样PHP在出现问题时会抛出一个AssertionError
。
有关更多信息,请参阅文档:https://secure.php.net/manual/en/function.assert.php
组件
扩展点
扩展此库的包应实现两个基本接口,它们用于抽象每个路由库的工作方式
Chimera\Routing\RouteParamsExtractor
:返回匹配路由的参数列表Chimera\Routing\UriGenerator
:根据给定的参数生成路由
路由参数提取中间件
此中间件使用Chimera\Routing\RouteParamsExtractor
的实现将匹配路由的参数放入标准属性中,以便其他组件可以检索它们。
请求处理器
Chimera\Handler\CreateAndFetch
:执行创建资源的命令并立即执行查询,返回一个包含查询结果和位置头的未格式化响应 - 旨在用于处理 POST 请求Chimera\Handler\CreateOnly
:执行创建资源的命令,返回一个包含位置头的空响应 - 旨在用于处理 POST 请求(前一个的变体,但也可以用于异步API)Chimera\Handler\ExecuteAndFetch
:执行修改资源的命令并立即执行查询,返回一个包含查询结果的未格式化响应 - 旨在用于处理 PUT 或 PATCH 请求Chimera\Handler\ExecuteOnly
:执行修改或删除资源的命令,返回空响应 - 用于处理 PUT、PATCH 或 DELETE 请求(也可用于异步API)Chimera\Handler\FetchOnly
:执行查询以获取资源,返回未格式化的查询结果响应 - 用于处理 GET 请求
用法
中间件管道
如上所述,内容协商不是请求处理器的责任。预期您将配置 lcobucci/content-negotiation-middleware
来处理此类任务,并且它应放在管道的最前面,以便它可以处理 任何 未格式化的响应。
Chimera\Routing\RouteParamsExtractor
中间件应放在负责匹配路由的中间件之后(每个实现都有所不同)。
因此,在 Zend Expressive v3 应用程序 中的中间件管道看起来像这样 - 假定所有服务都已在DI容器中正确配置
<?php declare(strict_types=1); use Chimera\Routing\RouteParamsExtraction; use Lcobucci\ContentNegotiation\ContentTypeMiddleware; use Psr\Container\ContainerInterface; use Zend\Expressive\Application; use Zend\Expressive\Handler\NotFoundHandler; use Zend\Expressive\Helper\BodyParams; use Zend\Expressive\Helper\ServerUrlMiddleware; use Zend\Expressive\Helper\UrlHelperMiddleware; use Zend\Expressive\MiddlewareFactory; use Zend\Expressive\Router\Middleware\DispatchMiddleware; use Zend\Expressive\Router\Middleware\ImplicitHeadMiddleware; use Zend\Expressive\Router\Middleware\ImplicitOptionsMiddleware; use Zend\Expressive\Router\Middleware\MethodNotAllowedMiddleware; use Zend\Expressive\Router\Middleware\RouteMiddleware; use Zend\Stratigility\Middleware\ErrorHandler; return function (Application $app, MiddlewareFactory $factory, ContainerInterface $container) : void { $app->pipe(ErrorHandler::class); $app->pipe(ServerUrlMiddleware::class); // Handles content negotiation, ensuring that the response format is the best one // according to what was requested via the `Accept` header $app->pipe(ContentTypeMiddleware::class); $app->pipe(RouteMiddleware::class); // Puts the matched arguments in a standard place (must be executed after the // `Zend\Expressive\Router\Middleware\RouteMiddleware` middleware, otherwise // matched routed info is not available) $app->pipe(RouteParamsExtraction::class); // It's quite important to add this one to the list, so that we ensure // that the request body is properly parsed and can be retrieved via // `ServerRequestInterface#getParsedBody()` - used by the `HttpRequest` input $app->pipe(BodyParams::class); $app->pipe(ImplicitHeadMiddleware::class); $app->pipe(ImplicitOptionsMiddleware::class); $app->pipe(MethodNotAllowedMiddleware::class); $app->pipe(UrlHelperMiddleware::class); $app->pipe(DispatchMiddleware::class); $app->pipe(NotFoundHandler::class); };
路由
此包的主要思想是将应用程序的行为移动到命令和查询处理器,这样它们就可以通过不同的交付机制进行重用。这意味着请求处理器的逻辑几乎是可重用的,因此您最终会拥有更少的代码需要维护。
考虑到您已使用正确的处理器配置了命令和查询总线,并且您已在依赖注入容器中映射了请求处理器的实例,您只需配置PSR-15路由器以将处理器添加到正确的端点。
在 Zend Expressive v3 应用程序 中,config/routes.php
的外观如下
<?php declare(strict_types=1); use Psr\Container\ContainerInterface; use Zend\Expressive\Application; use Zend\Expressive\MiddlewareFactory; /** * Considering you have the following services in your DI container: * * - `album.list` => new FetchOnly( * new ExecuteQuery(**query bus**, **message creation strategy**, MyApi\FetchAlbumList::class), * ResponseInterface::class * ); * - `album.find_one` => new FetchOnly( * new ExecuteQuery(**query bus**, **message creation strategy**, MyApi\FindAlbum::class), * ResponseInterface::class * ); * - `album.create` => new CreateOnly( * new ExecuteCommand(**command bus**, **message creation strategy**, MyApi\CreateAlbum::class), * ResponseInterface::class, * 'album.find_one', * UriGenerator::class, * IdentifierGenerator::class, * 201 * ); * - `album.update_album` => new ExecuteAndFetch( * new ExecuteCommand(**command bus**, **message creation strategy**, MyApi\UpdateAlbum::class), * new ExecuteQuery(**query bus**, **message creation strategy**, MyApi\FindAlbum::class), * ResponseInterface::class * ); */ return function (Application $app, MiddlewareFactory $factory, ContainerInterface $container) : void { $app->get('/album', 'album.list', 'album.list'); $app->post('/album', 'album.create', 'album.create'); $app->get('/album/{id}', 'album.find_one', 'album.find_one'); $app->patch('/album/{id}', 'album.update_album', 'album.update_album'); };
许可证
MIT,请参阅 LICENSE。