baraja-core/smart-router

此软件包已被弃用且不再维护。未建议替代软件包。
此软件包最新版本(v2.0.0)的许可证信息不可用。

v2.0.0 2021-02-11 12:44 UTC

README

Integrity check

路由器是一个在URL和应用请求之间进行双向转换的组件。双向转换意味着可以从URL推导出展示器动作,反之亦然,生成对应动作的URL。

此软件包提供SmartRouter的默认实现,它改进了Nette的默认路由方法,并添加了将特定URL及其参数、语言和高级配置存储在数据库(或其他存储库)中的功能。

安装

该软件包是默认Baraja 沙盒的一部分。

或者,您可以通过Composer手动安装

$ composer require baraja-core/smart-router

所有路由规则都定义在RouterFactory类中,我们可以像这样注入SmartRouter服务:

public static function createRouter(SmartRouter $smartRouter): RouteList
{
    $router = new RouteList;

    // Register SmartRouter
    $router[] = $smartRouter;

    // Optionally add additional routes or a collection of routes
    $router[] = self::createFrontRouter();

    return $router;
}

我们将确保所有请求首先通过SmartRouter处理,只有当失败时才会使用其他常规路由。

SmartRouter

SmartRouter是我对路由应如何工作的内部实现。整个请求路由过程完全自动进行,并且可以通过非常详细的配置进行影响,然后将其缓存。

我们将路由分为3个独立的部分

  • Match:将URL重写到应用请求(请求处理)
  • Construct URL:基于应用请求创建URL
  • Rewriter:实现URL部分参数重写接口,其中大部分魔法发生在这里

默认的Rewriter实现是DoctrineRewriter更多信息),它基于数据库表进行URL路由。其内部实现非常高效。

对于较小应用程序或测试情况,您可以使用StaticRewriter,它根据存储在数组中的物理数据进行重写。

Match - 接受请求URL

以下文本描述了如何根据加载的URL编译找到的参数列表。

路由分为4个逻辑步骤。

  1. 在缓存中查找所需的URL。如果记录存在(也可以是负的),我们直接路由它,不再进一步搜索
  2. 准备缓存以供配置,如果有的话,我们将从缓存中使用
  3. 根据内部逻辑(以下将描述)查找当前URL(路由)
  4. 将路由参数保存到键值缓存中,它将在第一步中再次使用。

请求缓存包含2个参数

  • 使用常量CACHE_EXPIRATION(默认30分钟)过期
  • 使用值route/<presenter>:<action>进行标记

注意:特殊行为

我们能够处理的所有请求仍然在路由器内部进行处理,路由器会始终添加locale键。如果在路由过程中未指定,我们将返回当前站点的默认语言。如果默认语言不存在,我们将返回英语。

如果匹配请求的当前语言不存在,我们将抛出E_NOTICE级别的错误。

发送和处理匹配的应用程序请求

无论我们在缓存中找到的是应用程序请求还是直接匹配创建的,它都始终通过returnRequest()方法发送。

此方法的任务是将当前环境(私有属性environment)设置为路由器的内部状态,这将用于路由其他请求和编译URL。如果当前匹配的环境比内部设置的环境更好,则将仅使用当前匹配的环境。

环境优先级评分表存储在environmentScoreTable配置键中,基本实现如下:

  • localhost: 1
  • beta: 2
  • production: 3

同时,此方法的任务是将语言设置为翻译器。

注意:如果在进一步处理应用程序和生成链接时没有路由请求,则无法可靠地确定语言和环境。

例如,如果我们以CLI模式(cron或其他后台任务)生成指向电子邮件的链接,则始终必须将语言(locale)和环境(environment)插入到所有请求中。如果我们不输入这些值,路由器可能的行为与我们预期的不同。

实体MatchRequest - 请求处理的内部逻辑

MatchRequest实体作为处理当前URL并返回结果的辅助工具。实例由Smart路由器本身创建。

只有在调用单个公共方法match()后才会进行最终处理,该方法在成功时返回参数字段,在错误或无效请求时返回null

处理内部逻辑可能会随时间改变(并改进),本文只描述了基本原则。具体实现和解释可以直接在实现中的注释中找到。

处理流程

  1. 查找路由(processRoute()方法)

目前我们只支持FrontAdmin模块,我们正在寻找匹配的presenteraction

我们逐步尝试规则

  • 是否为主页或空URL?($slug === ''
  • 是否有管理请求?如果有,我们将根据掩码admin/[<locale=en cs|en>/]<presenter>/<action>常规路由。
  • 基于Rewriter的转录+添加参数、环境和语言。
  • 正则表达式(对应于<presenter> / <action>掩码)用于与旧或lazy URL的向后兼容。
  1. 我们将处理请求的语言

请求的最终语言很难确定,因为在设计路由内核时,我们遇到了几十种特殊案例,其中**不容易**做出决定。它通常是域名语言与另一个语言slugu或locale参数的组合。

解决方案在于积累有关当前URL的所有可用语言,根据键将其排序到字段中,然后根据优先级选择最佳语言。

我们区分3个基本优先级级别

  • (最佳)URL参数:包含在?locale=en
  • 路径/别名:根据重写将URL的一部分分配给特定语言
  • 域名:语言是当前路由域的典型语言。
  1. 最终参数的编译

在本步骤中,将执行参数的最后检查和清除,并将其作为应用程序请求发送。

最小配置始终包含值

  • presenter(形式为<module>:<presenter>
  • 动作
  • locale(字符串)
  • environment(字符串,值:localhostbetaproduction

构造URL - 构建URL

以下文本描述了根据指定的参数生成URL的方法。

在生成URL本身之前,需要验证基本键的存在,根据这些键我们将确定URL的类型。

关于

  • locale:URL可用的语言
  • environment:URL指向的环境(例如,避免在beta上生成指向production或其他组合的链接)
  1. 根据参数组合的键,我们在缓存中找到URL
  2. 如果缓存不包含生成的URL,我们将准备配置或从缓存中读取它
  3. 基于内部逻辑(如下所述)构建所需的URL
  4. 写入缓存并返回最终的URL,或者在无法崩溃的情况下返回null

编译URL的过程比匹配更具挑战性,必须考虑更多的规则。然而,某些部分的工作方式相同。

正确生成的URL的基础是其唯一性,即使在将来也是如此。它不得包含逻辑冲突(例如,短语的语种不适合域名语种),因此使用了极其复杂的逻辑和一组规则进行组装。

在构建最终URL之前,创建了一个ConstructUrlRequest实体的实例,该实例需要(array $params, Rewriter $rewriter, array $config = null)并设置实体的内部状态,以便根据配置进一步生成。

在编译时,我们将找到以下值

  • environment:我们将生成URL的环境(例如,对于localhost或域生产,可能不同),
  • locale:URL语言
  • lazy:一个bool标志,指示一个简单地组装的常规URL,不使用Rewriter,这可能会减慢速度 - 如下文所述,
  • presenteraction用于页面类型上下文。

组装本身仅在调用construct()方法时进行,该方法返回包含绝对URL的string或发生错误时返回null

程序又有很多步骤

  1. 获取域名
  • 环境是否为空、未知或配置中未为其定义默认域名?那么将保留当前域名。
  • 如果环境存在,我们将找到最适合所需语言的域名
  • 如果不存在所需语言的域名,我们将返回环境的默认域名,并记住needLocaleParameter标志,表示我们必须在URL的参数中传递语言。

在返回域名之前,我们检查配置以查看是否应在域名之前添加www.useWww标志)。

  1. 处理pathslug

现在这取决于我们是否根据实际参数(使用Rewriter接口)构建路径,或者它是一个lazy link,即简化版本。

简化链接生成形式为<presenter>/<action>的路径,为Homepage:default仅生成/,为Product:default仅生成/product等等。

关于实际链接,我们使用 Rewriter 中的 rewriteByParameters() 方法生成 URL,而路由器的内部逻辑则执行进一步的清理,例如比较语言和删除重写的参数。更多详情请参考关于转录器的部分。

  1. 我们将根据以下通用格式编译最终的 URL

<方案>://<域名>/<路径>?<参数>

懒 URL - 简化 URL 格式

智能路由器支持所谓的 懒 URL,这是一种使用正则表达式生成的永久 URL,在编译和解析过程中不需要访问 Rewriter 或数据库。

其优点是读取和创建速度极快。特别适用于大型项目列表(如目录中的产品),构建一个 * 美观的 URL * 会花费不必要的长时间,并完全延迟页面加载。

懒 URL 在生成时通过传递值 ['lazy' => true] 来生成。

Rewriter

为了能够动态地将 URL 重新写为应用程序请求(参数)并返回(生成 URL),有必要实现一个 智能路由器,它提供了一般算法来完成这项任务。

然而,在实际应用中,不同的客户端需要以不同的方式重新编写 URL - 但主要是从数据库中。此 Rewriter 接口用于此任务,在需要更改编译 URL 的方法或从静态文件(小型网站或测试进度)重新编写时,这一点尤为重要。

rewriteByPath(string $path):?array;

在参数字段中覆盖当前路径(别名)。如果没有,则返回 null

最小配置以返回

[
   'presenter' => 'Front:Homepage',
   'action' => 'default',
   'locale' => 'en',
] + other parameters

rewriteByParameters 接口 (array $parameters):?RewriterParametersMatch;

在别名和其他属性上覆盖所需的参数。以类型实体返回结果。

RewriterParametersMatch 实体的任务是携带关于 URL 被重新编写到哪个 path别名),哪种语言以及使用了哪些参数的严格信息。

示例

在路由 /wheels URL 时,在 Front:Category:detail 上执行了重新编写,参数为 id = 1

我们必须将此参数单独传递到字段中,因为路由器将参数 id = 1 覆盖到别名 /kola 中,这明显表示此 ID。删除也是必要的,以便参数不会进一步保留在 URL 中,因为它已经作为别名的部分(在数据库中)传递,因此可以始终重新路由。

📄 许可证

baraja-core/smart-router 使用 MIT 许可证。有关更多详细信息,请参阅 LICENSE 文件。