archict/router

简单的HTTP路由器

维护者

详细信息

github.com/Archict/router

源代码

问题

安装: 232

依赖项: 2

建议者: 0

安全性: 0

星标: 0

关注者: 0

分支: 0

开放问题: 2

类型:archict-brick

v1.0.2 2024-09-14 09:10 UTC

README

Tests

用法

这个砖块允许您使用请求处理器设置路由并添加一些中间件。让我们看看如何做到这一点!

一个简单的路由...

创建路由有两种方式:拥有一个完整的控制器类,或者一个简单的闭包。

首先,您需要监听 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'

您有两种选择

  1. 传递一个字符串,Archict 将将其用作响应体
  2. 传递一个实现接口 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!"));
    }
}

您的类也可以有依赖项,就像服务一样,只需在构造函数中添加即可。这些依赖项必须是可用的服务。