archict / router
简单的HTTP路由器
Requires
- php: >= 8.2
- ext-simplexml: *
- archict/brick: ^1.0
- archict/core: ^1.0
- cuyz/valinor: ^1.12
- guzzlehttp/psr7: ^2.6
- psr/http-message: ^2.0
Requires (Dev)
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^10
- slevomat/coding-standard: ^8.15
- squizlabs/php_codesniffer: ^3.9
- vimeo/psalm: ^5.22
This package is auto-updated.
Last update: 2024-09-27 05:59:20 UTC
README
用法
这个砖块允许您使用请求处理器设置路由并添加一些中间件。让我们看看如何做到这一点!
一个简单的路由...
创建路由有两种方式:拥有一个完整的控制器类,或者一个简单的闭包。
首先,您需要监听 RouteCollectorEvent
事件。
<?php use Archict\Brick\Service; use Archict\Brick\ListeningEvent; use Archict\Router\RouteCollectorEvent; #[Service] class MyService { #[ListeningEvent] public function routeCollector(RouteCollectorEvent $event) { } }
然后,只需使用事件对象创建路由。
使用闭包
$event->addRoute(Method::GET, '/hello', static fn() => 'Hello World!');
闭包可以接受一个 Request
作为参数,并返回一个字符串或一个 Response
。
使用控制器类
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; $event->addRoute(Method::GET, '/hello', new MyController()); class MyController implements RequestHandler { public function handle(ServerRequestInterface $request): ResponseInterface { return ResponseFactory::build() ->withStatus(200) ->withBody('Hello World!') ->get(); } }
您的控制器必须实现 RequestHandler
接口。方法 handle
可以返回一个字符串或一个 Response
。
请注意,每个路由只能定义一个处理器。
方法 RouteCollectorEvent::addRoute
的第一个参数必须是一个允许的HTTP方法字符串。枚举 Method
包含允许的方法列表。如果您的路由可以匹配多个方法,您可以通过传递一个方法数组或 Method::ALL
。
第二个参数是您的路由,它可以是简单的静态路由,也可以是动态路由。在后一种情况下,每个动态部分必须写在 {}
之间。其中包含两个部分,由 :
分隔,一部分是名称,一部分是模式。动态部分的名称允许您在 Request
对象中轻松检索它。
模式可以是空的,在这种情况下,它将匹配到下一个 /
(或末尾)的所有字符,或者它可以是带有一些快捷方式的正则表达式。
\d+
匹配数字[0-9]+
\l+
匹配字母[a-zA-Z]+
\a+
匹配数字和字母[a-zA-Z0-9]+
\s+
匹配数字、字母和下划线[a-zA-Z0-9_]+
您还可以使用 [/suffix]
为路由添加可选后缀。
例如:/article/{id:\d+}[/{title}]
。
如果在处理过程中出现错误,您可以使用 HTTPExceptionFactory
构建异常。异常将被路由器捕获并用于构建响应。
...使用中间件
有时您需要在处理请求之前做一些处理。为此,存在中间件。您可以定义任意多的中间件。定义一个,过程与简单路由类似。
<?php use Archict\Brick\Service; use Archict\Brick\ListeningEvent; use Archict\Router\RouteCollectorEvent; use Psr\Http\Message\ServerRequestInterface; #[Service] class MyService { #[ListeningEvent] public function routeCollector(RouteCollectorEvent $event) { $event->addMiddleware(Method::GET, '/hello', static function(ServerRequestInterface $request): ServerRequestInterface { // Do something return $request }); // Or $event->addMiddleware(Method::GET, '/hello', new MyMiddleware()); } }
如果您使用闭包定义中间件,则它必须返回一个 Request
。如果是对象,则您的类必须实现 Middleware
接口。
use Psr\Http\Message\ServerRequestInterface; class MyMiddleware implements Middleware { public function process(ServerRequestInterface $request): ServerRequestInterface { return $request; } }
您可以在中间件中做任何想做的事情。如果出错,则过程与 RequestHandler 相同。
特殊响应处理
这里的“特殊”是指404、500等。简而言之,就是不同于2XX的HTTP状态码。默认情况下,Archict 将使用 ResponseHandler
,它仅设置相应的标题。通过此砖块的配置文件,您可以更改此行为。
error_handling: 404: \MyHandler 501: 'Oops! Something went wrong'
您有两种选择
- 传递一个字符串,Archict 将将其用作响应体
- 传递一个实现接口
ResponseHandler
的类的字符串,Archict 将调用它。例如
<?php use Archict\Router\ResponseHandler; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; class MyHandler implements ResponseHandler { public function handleResponse(ResponseInterface $response, ServerRequestInterface $request): ResponseInterface { $factory = new \GuzzleHttp\Psr7\HttpFactory(); return $response->withBody($factory->createStream("Page '{$request->getUri()->getPath()}' not found!")); } }
您的类也可以有依赖项,就像服务一样,只需在构造函数中添加即可。这些依赖项必须是可用的服务。