matthiasmullie / router
基于FastRoute的PSR-15路由接口
Requires
- php: ^8.1
- ext-json: *
- nikic/fast-route: ^1.3.0
- psr/http-message: ^1.0
- psr/http-message-implementation: ^1.0 || ^2.0
- psr/http-server-handler: ^1.0
- psr/http-server-middleware: ^1.0
- psr/log: ^1.0 || ^2.0 || ^3.0
Requires (Dev)
- friendsofphp/php-cs-fixer: >=3.0
- guzzlehttp/psr7: ^2.0
- monolog/monolog: ^3.0
- phpunit/phpunit: >=9.0
Suggests
- psr/log-implementation: Log router events
README
安装
如果您使用Composer来管理项目的依赖关系,只需在composer.json文件中添加对matthiasmullie/router
的依赖即可。
composer require matthiasmullie/router
使用方法
路由
此路由提供了一种简单的方法将路由(请求方法 + 路径)映射到请求处理器。
请求处理器是实现了PSR-15的Psr\Http\Server\RequestHandlerInterface
接口的类,它接受一个Psr\Http\Message\ServerRequestInterface
对象,并返回一个Psr\Http\Message\ResponseInterface
对象。
这本质上只是在FastRoute之上提供了一个简单的PSR-15层。
就是这么简单
use MatthiasMullie\Router\RequestMethods; use MatthiasMullie\Router\Router; use GuzzleHttp\Psr7\Response; use GuzzleHttp\Psr7\ServerRequest; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; // create 2 example request handlers class RouteOne implements RequestHandlerInterface { public function handle(ServerRequestInterface $request): ResponseInterface { return new Response( 200, ['Content-Type' => 'application/json; charset=utf-8'], json_encode(['message' => 'Hello world']), ); } } class RouteTwo implements RequestHandlerInterface { public function handle(ServerRequestInterface $request): ResponseInterface { return new Response( 200, ['Content-Type' => 'text/html; charset=utf-8'], '<html><body><p>Hello world</p></body></html>', ); } } // create router instance and add both routes $this->router = new Router(); $this->router->addRoute( RequestMethods::GET, '/one', new RouteOne(), ); $this->router->addRoute( RequestMethods::GET, '/two', new RouteTwo(), ); // route a request, receive response from the matching request handler $response = $router->handle( new ServerRequest('GET', '/one'), ); echo $response->getBody(); // outputs: {"message":"Hello world"}
分组
为了方便,具有相同前缀的路由可以捆绑在一起组成一个组。
例如
// create router instance and add an individual route $this->router = new Router(); $this->router->addRoute( RequestMethods::GET, '/one', // maps to /one new RouteOne(), ); // then 2 more routes with a shared prefix $group = $this->router->addGroup('/prefix'); $group->addRoute( RequestMethods::GET, '/two', // maps to /prefix/two new RouteTwo(), ); $group->addRoute( RequestMethods::GET, '/three', // maps to /prefix/three new RouteThree(), );
中间件
除了PSR-15的请求处理器之外,此路由还支持PSR-15的Psr\Http\Server\MiddlewareInterface
,它围绕请求处理器包装,在处理请求之前和之后执行。
这简化了多个请求处理器之间共享的逻辑,例如身份验证、日志记录等。
可以将中间件添加到单个路由、组内的所有路由或所有路由。
例如
class Middleware implements MiddlewareInterface { public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { // execute something before handling the request, // or manipulate the request object $request = $request->withAttribute('middleware', 'Hello world'); // invoke the handler (or the next middleware, if any) // and retrieve the response $response = $handler->handle($request); // execute something after handling the request, // or manipulate the response object return $response->withAddedHeader('Content-Type', 'application/json; charset=utf-8); } } // create router instance and add a route with middleware $this->router = new Router(); $this->router ->addRoute( RequestMethods::GET, '/one', new RouteOne(), ) ->addMiddleware( new Middleware(), ); // or add a group with middleware that applies to all routes within that group $this->router ->addGroup('/prefix') ->addMiddleware( new Middleware(), ) ->addRoute( RequestMethods::GET, '/two', new RouteTwo(), ); // or add middleware that applies to all routes $this->router->addMiddleware( new Middleware(), );
异常
默认情况下,无论是在请求处理器/中间件中遇到,还是在路由中(例如无效路由),遇到的任何异常都将简单地抛出。然而,可以添加自定义异常处理器,它会捕获任何异常并返回一个响应。
可以通过向路由器提供MatthiasMullie\Router\ExceptionResponseInterface
实例来完成此操作,例如提供的MatthiasMullie\Router\ExceptionResponse
。这将捕获任何异常并返回具有适当状态码的响应。
此包还附带一个自定义的MatthiasMullie\Router\Exception
类,允许在异常中包含HTTP状态码和头信息。
示例
use MatthiasMullie\Router\Exception; use MatthiasMullie\Router\ExceptionResponse; class RouteException implements RequestHandlerInterface { public function handle(ServerRequestInterface $request): ResponseInterface { throw new Exception('Not Implemented', 501); } } $this->router = new Router(new ExceptionResponse(new Response())); $this->router->addRoute( RequestMethods::GET, '/exception', new RouteException(), ); $response = $router->handle( new ServerRequest('GET', '/exception'), ); // $response now includes the 501 Not Implemented status code & reason phrase
许可证
router遵循MIT许可证。