icanboogie/routing

v5.0.0 2021-05-29 23:16 UTC

This package is auto-updated.

Last update: 2024-08-30 01:38:08 UTC


README

Packagist Code Quality Code Coverage Downloads

icanboogie/routing 包处理原生PHP中的URL重写。请求被映射到路由,路由再映射到响应器。如果处理成功,则返回响应。事件在过程中发出,以允许监听器修改请求或响应,或从失败中恢复。

以下示例是请求处理的概述。路由组件是响应器提供者堆栈的一部分。

<?php

namespace ICanBoogie\HTTP;

/* @var ResponderProvider $responder_provider */

// The request is usually created from the $_SERVER super global.
$request = Request::from($_SERVER);

// The Responder Provider matches a request with a Responder
$responder = $responder_provider->responder_for_request($request);

// The Responder responds to the request with a Response, it might also throw an exception.
$response = $responder->respond($request);

// The response is sent to the client.
$response();

安装

composer require icanboogie/routing

路由

路由用 Route 实例表示。创建实例需要两个参数:patternactionpattern 是匹配或生成URL的模式。action 是一个用于匹配响应器的操作标识符。

路由模式

模式用于匹配URL与路由。可以使用占位符将多个URL匹配到单个路由并提取其参数。有三种类型的占位符可用

  • 宽松占位符:仅指定参数的名称,它匹配任何直到下一个部分的内容。例如:/articles/:id/edit

  • 约束占位符:使用正则表达式匹配参数值。例如:/articles/<id:\d+>/edit,其中 <id:\d+>id 参数的占位符,其值必须匹配 /^\d+$/

  • 匿名约束占位符:与约束占位符相同,但参数没有名称,而是一个索引,例如:/articles/<\d+>/edit,其中 <\d+> 是一个占位符,其索引为0。

此外,joker字符 * 可以在模式的末尾使用,它匹配任何内容。例如:/articles/123* 匹配 /articles/123/articles/123456

最后,约束正则表达式扩展如下

  • {:sha1:}:匹配 SHA-1 哈希。例如:/files/<hash:{:sha1:}>
  • {:uuid:}:匹配 UUID(通用唯一标识符)。例如:/articles/<uuid:{:uuid:}>/edit

您可以将它们组合使用

  • /blog/:year-:month-:slug
  • /blog/<year:\d{4}>-<month:\d{2}>-:slug
  • /images/<uuid:{:uuid:}>/<size:\d+x|x\d+|\d+x\d+>*

路由提供者

路由提供者用于找到与谓词匹配的路由。简单的路由提供者通常被更复杂的提供者装饰,以提高性能。

以下是一个路由提供者使用的概述,详细信息请参阅 路由提供者文档

<?php

namespace ICanBoogie\Routing;

use ICanBoogie\HTTP\RequestMethod;
use ICanBoogie\Routing\RouteProvider\ByAction;
use ICanBoogie\Routing\RouteProvider\ByUri;

/* @var RouteProvider $routes */

$routes->route_for_predicate(new ByAction('articles:show'));
$routes->route_for_predicate(new ByUri('/articles/123', RequestMethod::METHOD_GET));
$routes->route_for_predicate(fn(Route $route) => $route->action === 'articles:show');

响应用户请求

如果路由匹配请求URI和方法,则可以将请求调度到匹配的响应器。

<?php

use ICanBoogie\HTTP\Request;
use ICanBoogie\HTTP\RequestMethod;
use ICanBoogie\HTTP\Responder;
use ICanBoogie\Routing\RouteProvider;

$routes = new RouteProvider\Immutable([

    new Route('/articles/<id:\d+>', 'articles:delete', RequestMethod::METHOD_DELETE)

]);

$request = Request::from([

    Request::OPTION_URI => "/articles/123",
    Request::OPTION_METHOD => RequestMethod::METHOD_DELETE,

]);

/* @var Responder $responder */

$response = $responder->respond($request);

控制器

之前的示例展示了如何使用闭包来处理路由。在开始构建应用程序时,闭包是完全可以接受的,但随着应用程序的增长,你可能希望使用控制器类来更好地组织你的应用程序。你可以将每个路由映射到其控制器类,或者使用ActionTrait来将相关的HTTP请求处理逻辑组合到单个控制器中。

控制器响应

当被调用时,控制器应该返回一个结果,或者在无法处理请求时返回null。`action()`方法的返回结果由`__invoke()`方法处理:如果结果是Response实例,则直接返回;如果控制器附加的Response实例已初始化(例如通过`$this->response`属性),则使用结果作为响应体;否则,直接返回结果。

在执行动作之前

Controller\BeforeActionEvent的事件`ICanBoogie\Routing\Controller::action:before`在调用`action()`方法之前触发。事件钩子可以使用此事件提供响应,从而取消动作。事件钩子也可以使用此事件在执行动作之前更改控制器。

在执行动作之后

Controller\ActionEvent的事件`ICanBoogie\Routing\Controller::action:after`在调用`action()`方法之后触发。事件钩子可以使用此事件更改方法的结果。

基本控制器

基本控制器从Controller扩展,必须实现`action()`方法。

注意:`action()`方法在控制器内部由`__invoke()`方法调用,应定义为`protected`。`__invoke()`方法是最终的,因此不能被重写。

<?php

namespace App\Modules\Articles\Routing;

use ICanBoogie\HTTP\Request;
use ICanBoogie\Routing\Controller;

class DeleteController extends Controller
{
    protected function action(Request $request)
    {
        // Your code goes here, and should return a string or a Response instance
    }
}

尽管任何实现`__invoke()`的类都适合作为控制器,但推荐扩展Controller,因为这使访问应用程序功能变得更加容易。此外,你可能还会从附加到Controller类的原型方法和事件钩子中受益,例如由icanboogie/view包添加的`view`属性。

Controller类提供的以下属性

  • name:控制器的名称,从其类名中提取,例如"articles_delete"。
  • request:正在分发中的请求。
  • route:正在分发的路由。

动作控制器

以下是一个动作控制器的示例,详细信息请参阅动作控制器文档

<?php

use ICanBoogie\Routing\ControllerAbstract;
use ICanBoogie\Routing\Controller\ActionTrait;

final class ArticleController extends ControllerAbstract
{
    use ActionTrait;

    private function list(): string
    {
        // …
    }

    private function show(): string
    {
        // …
    }
}

异常

该软件包定义的异常实现了ICanBoogie\Routing\Exception接口,因此易于识别

<?php

try
{
    // …
}
catch (\ICanBoogie\Routing\Exception $e)
{
    // a routing exception
}
catch (\Exception $e)
{
    // another type of exception
}

定义了以下异常

持续集成

该项目由 GitHub actions 进行持续测试。

Tests Static Analysis Code Style

行为准则

本项目遵循 贡献者行为准则。通过参与本项目及其社区,您应遵守此准则。

贡献

请参阅 CONTRIBUTING 了解详细信息。

许可证

icanboogie/routing 采用 BSD-3-Clause 许可。