quimcalpe/router

基于正则表达式的路由器,易于使用,功能丰富

3.0.0 2023-04-26 13:47 UTC

This package is auto-updated.

Last update: 2024-08-26 16:43:27 UTC


README

Version License Build Status Code Coverage Scrutinizer Code Quality

基于正则表达式的路由器,易于使用,功能丰富。它包括各种内置的调度器,我们还提供了一种接口来为您项目开发完全定制的调度器。

安装

通过Composer

$ composer require quimcalpe/router

要求

以下版本的PHP支持此版本。

  • PHP 8.1

基本用法

// Require composer autoloader
require __DIR__ . '/vendor/autoload.php';

use QuimCalpe\Router\Router;
use QuimCalpe\Router\Dispatcher\SimpleDispatcher;

// Create Router instance
$router = new Router();

// Define routes, last parameter defining route name is optional
$router->addRoute('GET', '/users', 'Quimi\Controllers\UserController', 'user_list');
$router->addRoute('GET', '/users/edit/{id:number}', 'Quimi\Controllers\UserController::edit', 'user_edit');
$router->addRoute(['POST', 'DELETE'], '/users/remove/{id:number}', 'Quimi\Controllers\UserController::remove', 'user_delete');

// Sugar methods for common verbs are also available (GET, POST, PUT, DELETE...)
$router->addGet('/user/{id}', 'Quimi\Controllers\UserController::show', 'user_show');

// You can also create a QuimCalpe\Router\Route\Route value object and add directly to router's `->add()`
$route = new Route('GET', '/', 'Quimi\Controllers\HomeController', 'home');
$router->add($route);

try {
    // Match routes
    $route = $router->parse($_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI']);
    // Dispatch route
    $dispatcher = new SimpleDispatcher();
    $response = $dispatcher->handle($route);
} catch (QuimCalpe\Router\Exception\MethodNotAllowedException $e) {
	header('HTTP/1.0 405 Method Not Allowed');
	// exception message contains allowed methods
	header('Allow: '.$e->getMessage());
} catch (QuimCalpe\Router\Exception\RouteNotFoundException $e) {
	header('HTTP/1.0 404 Not Found');
    // not found....
}

构造函数可选 Route[] 参数

您可以选择将 Route 对象数组传递给 Router 的构造函数,并创建路由;

use QuimCalpe\Router\Router;
use QuimCalpe\Router\Route\Route;

$routes = [
	new Route('GET', '/users', 'Quimi\Controllers\UserController', 'user_list'),
	new Route('GET', '/users/edit/{id:number}', 'Quimi\Controllers\UserController::edit', 'user_edit'),
	new Route(['POST', 'DELETE'], '/users/remove/{id:number}', 'Quimi\Controllers\UserController::remove', 'user_delete'),
]

$router = new Router($routes);

此数组可以来自另一个文件,从而以简单的方式实现配置分离。

路由提供者

如果您想从特定的包/命名空间/捆绑包导入大量路由,并希望保持路由的有序性,您可以使用路由提供者,如下定义您的提供者

namespace My\Package;

use QuimCalpe\Router\Route\Route;
use QuimCalpe\Router\Route\RouteProvider;

class MyPackageRoutes implements RouteProvider
{
    public function routes(): array
    {
        return [
            new Route('GET', '/users', 'Quimi\Controllers\UserController', 'user_list'),
            new Route('GET', '/users/edit/{id:number}', 'Quimi\Controllers\UserController::edit', 'user_edit'),
            new Route(['POST', 'DELETE'], '/users/remove/{id:number}', 'Quimi\Controllers\UserController::remove', 'user_delete'),
        ];
    }
}

然后使用以下方式初始化 Router

$router = new Router();
$router->addRouteProvider(new \My\Package\MyPackageRoutes());

路由模式

支持基本的正则表达式模式,其中一些已包含在内

  • [^/]+ 作为默认值
  • 'word' => \w+
  • 'number' => \d+
  • 'slug' => [A-Za-z0-9_-]+

可以使用这种方式使用模式

$router->addRoute('GET', '/users/edit/{id:number}', 'Controller::action');
$router->addRoute('GET', '/users/{name:word}', 'Controller::action');

您可以定义自己的模式

$router->addPattern("phone", "[0-9]-[0-9]{3}-[[0-9]{3}-[0-9]{4}"); // #-###-###-####
$router->addRoute("GET", "/customer/{phone:phone}", "Vendor\Package\Controller");
$parsedRoute = $router->parse("GET", "/customer/1-222-333-4444");

通配符

路由中的通配符可以使用 WildcardDispatcher 来使用

$router->addRoute('GET', '/test/{controller}/{action}/{id}', 'Vendor\Package\{controller}::{action}');
$parsedRoute = $router->parse("GET", "/test/user/edit");
$dispatcher = new WildcardDispatcher;
$response = $dispatcher->handle($parsedRoute); // => Vendor\Package\User::edit($id)

请求响应

支持使用 RequestResponseDispatcher 的标准请求-响应工作流程与 Symfony HttpFoundation 组件

use Symfony\Component\HttpFoundation\Request;
use QuimCalpe\Router\Router;
use QuimCalpe\Router\Dispatcher\RequestResponseDispatcher;

$router = new Router();
$router->addRoute('GET', '/users', 'Quimi\Controllers\UserController::index');

$request = Request::createFromGlobals();
$route = $router->parse($request->getMethod(), $request->getPathInfo());

// You can optionally modify the request object here before dispatching:
$request->attributes->set('foo', 'bar');

$dispatcher = new RequestResponseDispatcher($request);
$response = $dispatcher->handle($route);
$response->send();

PSR-7 HTTP 消息

内置的 PSR7Dispatcher 可用于与 PHP-FIG 的 PSR-7 HTTP 消息标准实现一起工作,例如使用 Zend Diactoros 和简单的 PSR-7 Response Sender 的示例如下

use QuimCalpe\Router\Router;
use QuimCalpe\Router\Route\Route;
use QuimCalpe\Router\Dispatcher\PSR7Dispatcher;
use function QuimCalpe\ResponseSender\send AS send_response;
use Zend\Diactoros\ServerRequestFactory;
use Zend\Diactoros\Response;

$router = new Router();
$router->add(new Route("GET", "/test", "ControllerFoo"));

$request = ServerRequestFactory::fromGlobals();
$route = $router->parse($request->getMethod(), $request->getUri()->getPath());

$dispatcher = new PSR7Dispatcher($request, new Response());
$response = $dispatcher->handle($route);
send_response($response);

自定义调度器

您可以创建自己的自定义调度器,实现 DispatcherInterface

interface DispatcherInterface
{
    public function handle(ParsedRoute $route): mixed;
}

QuimCalpe\Router\Route\ParsedRoute 是一个小的值对象,它具有由 Router::parse 解析的 controller()params() 方法。

尾部斜杠

默认行为是区分带有和没有尾部斜杠的路由

$router = new Router();
$router->addRoute('GET', '/users', 'Controller');
$router->parse('GET', '/users'); // => OK!
$router->parse('GET', '/users/'); // => NOT FOUND

您可以使用 disableTrailingSlashCheck 方法禁用此行为

$router = new Router();
$router->addRoute('GET', '/users', 'Controller');
$router->disableTrailingSlashCheck();
$router->parse('GET', '/users'); // => OK!
$router->parse('GET', '/users/'); // => OK!

测试

$ vendor/bin/phpunit

许可证

MIT 许可证 (MIT)。请参阅 许可证文件 以获取更多信息。