artyuum/router

另一个PHP请求路由器。

dev-master 2021-10-20 18:16 UTC

This package is auto-updated.

Last update: 2024-09-21 00:59:36 UTC


README

hello world

注意:此路由器尚未完全功能化,仍在开发中。将很快发布一个稳定版本。

功能

  • RESTful路由器。
  • 附带Symfony Http Foundation
  • 支持命名路由参数和占位符。(正在进行中)
  • 支持路由分组(以及嵌套分组)。
  • 支持命名路由(带有反向路由)。(正在进行中)
  • 支持路由前后中间件。
  • 支持全局中间件的前后。
  • 支持路由前缀。
  • 支持路由映射。
  • 支持自定义404处理器。

安装

composer require artyuum/router:dev-master

文档

注册路由

该路由器包含一些用于最常见HTTP方法的函数,可以帮助您轻松注册路由。

$router->get(string $uri, $handler);
$router->post(string $uri, $handler);
$router->put(string $uri, $handler);
$router->patch(string $uri, $handler);
$router->delete(string $uri, $handler);
$router->options(string $uri, $handler);

这些只是以下方法的包装:

$router->addRoute(array $methods, string $uri, $handler);

使用addRoute()方法,您可以注册一个匹配多个HTTP方法的路由。

$router->addRoute(['GET', 'POST'], string $uri, $handler);

路由器不会限制您的应用程序只使用最常用的HTTP方法。实际上,您还可以注册一个匹配自定义HTTP方法的路由。

$router->addRoute(['BLAH'], string $uri, $handler);

$handler参数必须是可调用的或数组(如果是类的话)。

// using an anonymous function
$router->get('/', function(\Symfony\Component\HttpFoundation\Request $request, \Symfony\Component\HttpFoundation\Response $response) {
    echo 'hello world';
});

// using a function name
$router->get('/', 'myFunction');

// using an array (if it's a class)
$router->get('/', [HomepageController::class, 'index']);

一旦请求与已注册的路由之一匹配,路由器将执行处理器,并按以下顺序传递两个参数:

  1. Symfony\Component\HttpFoundation\Request $request

  2. Symfony\Component\HttpFoundation\Response $response

这些参数是Symfony HTTP Foundation组件的一部分,并可以帮助您获取有关请求的更多信息,以及轻松构建并发送响应给客户端。您可以阅读文档以获取有关其使用的更多信息。

路由参数

可以使用占位符或纯正则表达式(PCRE)设置路由参数,如下所示:

$router->get('/profile/{username}', $handler); // will be internally converted to /profile/?<username>(\w+)

当使用纯正则表达式时,重要的是要给分组命名(如上所示)。否则,路由器将无法从URL中获取参数,它也无法使用url()方法正确地构建指向路由的URL。

默认情况下,占位符将被转换为匹配至少一个字母、数字或_的必选参数。您可以通过使用where()方法来更改此行为,如下所示:

$router->get('/profile/{id}', $handler)->where([
    'id' => '[0-9]+' // can also be written as "\d+"
]); // will match /profile/<one or n digit(s) from 0 to 9>

where(array $placeholders)方法接受一个关联数组作为参数,其中$key是占位符的名称,$value是正则表达式。

您还可以通过在占位符名称后附加一个"?"符号来将占位符设置为可选,如下所示:

$router->get('/profile/{username?}', $handler); // will match /profile OR /profile/<any word of at least one letter, number or _>

命名路由

命名路由允许您通过名称轻松找到已注册的Route对象。使用返回的对象,您将能够访问此对象的所有方法(例如getPath()getName()getMiddlewares()getHandler()等...)

示例

// registers a route named "homepage"
$router->get('/', $handler)->setName('homepage'); 

// registers a route named "user.delete"
$router->get('/users/{id}/delete', $handler)->setName('user.delete'); 

// gets the Route instance of the "homepage" route
$route = $route->getRoute('homepage');

// builds an url to a route
$url = $router->url('homepage'); // /home

// builds an url to a route with parameters
$url = $router->url('user.delete', ['id' => 1]); // /users/1/delete

路由分组

您可以使用group()方法对路由进行分组。这使得您能够为组内的所有路由设置前缀或中间件。

路由URI前缀

示例

// homepage
$router->get('/', $handler); // will match "/"

// admin
$router->group(function(\Artyum\Router\RouteGroup $group) use ($router)
{
    $group->setPathPrefix('/admin');
    $router->get('/', $handler); // will match "/admin"
});

路由名称前缀

示例

// homepage
$router->get('/', $handler); // will match "/"

// admin
$router->group(function(\Artyum\Router\RouteGroup $group) use ($router)
{
    $group->setNamePrefix('admin.');
    $router->get(string $uri, $handler)->setName('homepage'); // name will be "admin.homepage" 
});

路由中间件

示例

$router->group(function(\Artyum\Router\RouteGroup $group) use ($router)
{
    $group->addMiddlewares([
        'before' => [RateLimitMiddleware::class, AuthMiddleware::class],
        'after' => [LoggingMiddleware::class]
    ]);

    $router->get(string $uri, $handler);
    $router->post(string $uri, $handler);
});

如果请求与已注册的某个路由匹配,则路由器将按以下顺序执行以下操作

  1. 首先,执行RateLimitMiddleware类的handle()方法。
  2. 其次,执行AuthMiddleware类的handle()方法。
  3. 第三,执行匹配的路由控制器。
  4. 最后,执行LoggingMiddleware类的handle()方法。

路由器将自动执行中间件类的handle()方法,因此您不需要指定它。

您还可以将路由前/后中间件添加到组中,如下所示

$router->group(function(\Artyum\Router\RouteGroup $group) use ($router)
{
    $group->setBeforeMiddlewares([RateLimitMiddleware::class, AuthMiddleware::class]);
    $group->setAfterMiddlewares([LoggingMiddleware::class]);
});

这些仅仅是围绕addMiddlewares()方法的包装器。

路由映射

您可以将单个URI映射到多个不同的HTTP方法和不同的处理器,如下所示

$router->map('/users/{id}')
    ->put($handler)
    ->patch($handler)
    ->delete($handler);

使用withAttributes()方法,您将能够访问路由对象,以便为路由设置额外的属性

$router->map('/users/{id}')
    ->put($handler)->withAttributes(function(\Artyum\Router\Route $route) {
        $route
            ->setName('user.replace')
            ->setBeforeMiddlewares([RateLimitMiddleware::class, RolesMiddleware::class]);
     })
    ->patch($handler)->withAttributes(function(\Artyum\Router\Route $route) {
        $route
            ->setName('user.update')
            ->setBeforeMiddlewares([RateLimitMiddleware::class, RolesMiddleware::class]);
    })
    ->delete($handler)->withAttributes(function(\Artyum\Router\Route $route) {
        $route
            ->setName('user.delete')
            ->setBeforeMiddlewares([RateLimitMiddleware::class, RolesMiddleware::class]);
    });

还可以将映射的路由添加到组中,这样您就可以为组内的所有路由设置中间件,并且还可以设置名称前缀

$router->group(function(\Artyum\Router\RouteGroup $group) use ($router)
{
    $group->setBeforeMiddlewares([RateLimitMiddleware::class, RolesMiddleware::class]);
    $group->setNamePrefix('user.');

    $router->map('/users/{id}')
        ->put($handler)->withAttributes(function(\Artyum\Router\Route $route) {
            $route->setName('replace');
         })
        ->patch($handler)->withAttributes(function(\Artyum\Router\Route $route) {
            $route->setName('update');
        })
        ->delete($handler)->withAttributes(function(\Artyum\Router\Route $route) {
            $route->setName('delete');
        });
});

路由未找到

默认情况下,当请求不匹配任何已注册的路由时,dispatch()方法将抛出“NotFoundException”。您可以通过注册处理器来更改此行为。注册的处理器将与控制器或中间件相同的参数执行。

setNotFoundHandler($handler);

示例

// sends a 404 status code if no routes match the current request
$router->setNotFoundHandler(function(\Symfony\Component\HttpFoundation\Request $request, \Symfony\Component\HttpFoundation\Response $response) {
    $response
        ->setStatusCode(404)
        ->send();
});

贡献

如果您想做出贡献,请fork仓库并根据您的意愿进行更改。我们热情地欢迎拉取请求。