mvccore/ext-router-module

MvcCore - 扩展 - 路由 - 模块 - 用于在单个项目中管理多个网站,由域路由定义,通过模块属性在URL完成时定位。

v5.2.0 2023-12-12 13:07 UTC

This package is auto-updated.

Last update: 2024-09-26 14:33:08 UTC


README

Latest Stable Version License PHP Version

MvcCore 路由扩展,用于在单个项目中管理多个网站,由域路由定义,通过模块属性在URL完成时定位。

此路由是路由请求的方式,在域级别使用参数或变量部分,命名空间,默认参数值等。

大纲

  1. 安装
  2. 功能
    2.1. 功能 - 路由
    2.2. 功能 - URL 生成
  3. 工作原理
    3.1. 工作原理 - 路由
    3.2. 工作原理 - URL 完成时
  4. 使用方法
    4.1. 使用方法 - Bootstrap 初始化
    4.2. 使用方法 - 定位自定义应用程序部分
    4.3. 使用方法 - 创建模块域路由
    4.4. 使用方法 - 域路由和标准路由定义

1. 安装

composer require mvccore/ext-router-module

回到顶部

2. 功能

2.1. 功能 - 路由

  • 路由器与域名一起工作,并通过请求参数中的不同模块名称定位请求。
  • 路由器可以通过在“域路由”中定义的命名空间定位各种应用程序控制器命名空间(各种应用程序部分)。
  • 路由器存储另一组路由,称为“域路由”。
  • 在标准路由器路由之前处理域路由路由。对于重写路由的路由策略,以及对于基于查询字符串的路由策略。
  • 每个域路由都有必需的 module 名称和 pattern 属性(或与 reverse 一起的 match),仅描述方案和域名URL部分(或基本路径)。如果路由与传入请求的基本部分匹配,则通过匹配的域路由将 module 名称分配到请求参数中。然后通过标准路由处理标准路由。
  • 每个域路由都可以为标准路由或查询字符串定义的控制器定义 namespace 属性,如果该控制器路径未绝对定义——如果它不以单个反斜杠 \ 或双斜杠 // 开头。
  • 每个标准路由都可以定义一个名为 allowedModules 的高级配置属性,该属性为字符串数组,描述了对于哪个模块名称允许该路由。如果路由未定义该高级属性,则表示“路由对所有模块允许”。
  • 任何标准路由仍然可以绝对定义 pattern(或 matchreverse)。然后仅在该路由的固定定义的域或方案中用于匹配过程。

回到顶部

2.2. 功能 - URL 生成

  • 路由器可以通过在 Url 方法的第二个参数——$params 数组中添加带有目标模块名称的 module 记录,仅针对不同的模块生成 URL 地址。
  • 如果第二个参数 $params 中没有 module 记录,则不会生成 URL 的绝对部分,只有当标准路由需要它或者第二个参数 $params 中存在值为 TRUEabsolute 记录时才生成。
  • 规范 URL 地址和 self URL 地址也通过模块域路由来解决。

回到顶部

3. 工作原理

3.1. 工作原理 - 路由

  • 在解决路由策略并且处理标准路由之前,先处理模块域路由。
  • 处理完模块域路由后,初始化当前模块域路由。
  • 然后检查每个处理的常规路由是否存在允许的模块名称,如果不允许,则跳过该路由。
  • 在路由之后,如果匹配到任何具有命名空间且目标控制器未绝对定义的模块域路由,则在目标控制器路径之前添加模块路由命名空间。
  • Bootstrap.php 中使用方法 $router->SetDomainRoutes(...); 定义模块域路由是推荐但不必要的。

回到顶部

3.2. 工作原理 - URL 完成功能

  • 如果第二个参数 $params 数组中定义了 module 记录名称,则通过模块域路由完成基础 URL 部分(协议、域名和基础路径)。
  • 如果常规路由已定义绝对部分,或者常规路由被定义为绝对且第二个参数 $params 数组中指定了任何不同的 module 记录名称,则会生成错误,因为这是逻辑冲突。

回到顶部

4. 使用方法

4.1. 使用方法 - Bootstrap 初始化

将此内容添加到 Bootstrap.php 或在 应用开始时,在应用路由或其他使用路由的扩展配置之前

$app = \MvcCore\Application::GetInstance();
$app->SetRouterClass('\MvcCore\Ext\Routers\Module');
...
// to get router instance for next configuration:
/** @var \MvcCore\Ext\Routers\Module $router */
$router = \MvcCore\Router::GetInstance();

回到顶部

4.2. 使用方法 - 定位自定义应用部分

模块域路由是定义应用部分的一种特殊路由方式,而不是直接定义控制器或操作。
自定义应用部分的定义设计得非常自由,以便您能够做任何您想做的事情。

  • 您的自定义应用部分也可以在模块域路由中定义为命名空间,当控制器未绝对定义(以单个反斜杠开头或以双斜杠开头)时,由标准路由通过路由的控制器进行使用。
  • 您的自定义应用部分也可以通过允许的模块定义来定义,添加到任何标准路由中。通过这种方式,您可以定义哪些标准路由可用于哪些模块。可以有多个允许的模块名称或没有(NULL 表示所有模块都允许)。
  • 您的自定义应用部分也可以通过特殊参数名称 module 来定义。每次匹配任何模块域路由时,都会在请求对象中添加此参数。其值通过域名路由模块名称进行完成。此参数仅用于描述目的,用于从模块生成 URL。但您可以在控制器处理和渲染中用它来完成任何其他任务,以生成应用结果。

回到顶部

4.3. 使用方法 - 创建模块域路由

  • 模块域路由是定义应用部分的一种特殊路由方式,而不是直接定义控制器或操作。
  • 模块域路由模式可以包含任何参数或变量部分,就像常规路由一样,它可以包含像常规路由一样的域名 URL 部分的百分比动态替换(如 %domain%%tld% ...),但除了方案定义(http://https:////)和域名部分(如果需要,还包括基础部分)之外,不能包含其他任何内容。
  • 模块域路由直接扩展自标准 \MvcCore\Route 类。
  • 域路由也可以定义为单个配置数组,该数组传递给模块域路由构造函数,当您通过方法 SetDomainRoutes()AddDomainRoutes()AddDomainRoute() 在路由实例上定义模块域路由时。
// Instance by specified all constructor params:
new \MvcCore\Ext\Routers\Modules\Route(
    "//blog.%sld%.%tld%",             // pattern
    "blog",        "Blog",            // module, namespace
    ["page" => 1], ["page" => "\d+"], // defaults, constraints
    [                                 // advanced configuration
        "allowedLocalizations" => ["en-US"],     // only for extension `mvccore/ext-router-localization`
        "allowedMediaVersions" => ["full" => ""] // only for extension `mvccore/ext-router-media`
    ]
);

// Or instance by single configuration array:
new \MvcCore\Ext\Routers\Modules\Route([
    "pattern"              => "//blog.%sld%.%tld%",
    "module"               => "blog",
    "namespace"            => "Blog",
    "defaults"             => ["page" => 1],
    "constraints"          => ["page" => "\d+"],
    "allowedLocalizations" => ["en-US"],     // only for extension `mvccore/ext-router-localization`
    "allowedMediaVersions" => ["full" => ""] // only for extension `mvccore/ext-router-media`
]);

// Or instance by single configuration array with directly defined 
// regular expression `match` pattern and `reverse` pattern`:
new \MvcCore\Ext\Routers\Modules\Route([
    "match"                => "#^//blog\.%sld%\.%tld%$#",
    "reverse"              => "//blog.%sld%.%tld%",
    "module"               => "blog",
    "namespace"            => "Blog",
    "defaults"             => ["page" => 1],
    "constraints"          => ["page" => "\d+"],
    "allowedLocalizations" => ["en-US"],     // only for extension `mvccore/ext-router-localization`
    "allowedMediaVersions" => ["full" => ""] // only for extension `mvccore/ext-router-media`
]);

回到顶部

4.4. 使用方法 - 域路由和常规路由定义

要使用模块,您需要指定更多内容。与常规路由一样,您需要指定“模块域路由”。

// Define domain routes (domain routes also could be defined as single 
// configuration arrays passed into module domain route constructor):
$router->SetDomainRoutes([
    // to define blog website module:
    'blog'    => [
        'pattern'      => '//blog.example.com',
        'namespace'      => 'Blog',
    ],
    // to define main website module:
    'main'    => [
        'pattern'      => '//[<productsCategory>.]example.com',
        'constraints' => ['productsCategory' => '-a-z0-9]+'],
        'namespace'      => 'Main',
    ],
	// now all requests into `main` module will have `productsCategory` param
	// in request object. For request into `http://example.com/`, there will
	// be `NULL` value for this param, so you can recognize a homepage or there
	// are many other ways how to target a homepage.
]);

// Now let's define standard routes:
$router->SetRoutes([
    
    // Absolutely defined target controller in `\App\Controllers`:
    '\Admin\Index:Index'   => '/admin',
    
    // Relatively defined controllers in `\App\Controllers` by module route namespace:
    
    // There will be only used controllers `\Main\Categories` and
    // `\Main\Categories`, because there is allowed only `main` module.
    // Example match by: `http://phones.example.com/`, `http://phones.example.com/2`, ...
    'Categories:List'      => [
        'pattern'          => '/[<page>]',
        'defaults'         => ['page' => 1],
        'constraints'      => ['page' => '\d+'],
        'allowedModules'   => ['main'],
    ],
    // Example match by: `http://phones.example.com/products/brands-samsung/price-0-1000`, ...
    'Products:List'   => [
        'pattern'          => '/products[/<filter*>]',
        'constraints'      => ['filter' => '-a-zA-Z0-9_/]+'],
        'allowedModules'   => ['main'],
    ],
    // Example match by: `http://phones.example.com/product/samsung-galaxy-note-9/white`, ...
    'Products:Detail' => [
        'match'            => '#^/product/(?<id>\d+)(/(?<color>[a-z]+))?/?#',
        'reverse'          => '/product/<id>[/<color>]',
        'defaults'         => ['color' => 'red'],
        'allowedModules'   => ['main'],
    ],
    // There will be only used controller `\Blog\Posts`, 
    // because there is allowed only `blog` module.
    // Example match by: `http://blog.example.com/`, `http://blog.example.com/2`, ...
    'Posts:List'           => [
        'pattern'          => '/<page>]',
        'defaults'         => ['page' => 1],
        'constraints'      => ['page' => '\d+'],
        'allowedModules'   => ['blog'],
    ],
    // Example match by: `http://blog.example.com/post/which-phone-to-buy`, ...
    'Posts:Detail'         => [
        'pattern'          => '/post/[<path>]',
        'constraints'      => ['path' => '[-a-zA-Z0-9_/]+']
        'allowedModules'   => ['blog'],
    ],
    // There will be used controller `\Main\Index` but 
    // there could be also used controller `\Blog\Index`.
    // Example match by: `http://example.com/pages/contacts`, `http://blog.example.com/pages/contacts`, ...
    'Index:Index'          => [
        'pattern'          => '/pages/<path>',
        'constraints'      => ['path' => '[-a-zA-Z0-9_/]+'],
        //'allowedModules' => [NULL], //if there is allowed `NULL`, all modules are allowed
    ],    
]);

回到顶部