You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从Yii/Craft CMS的UrlRule中获取指定格式的路由

在Craft CMS中统一获取配置文件与模块注册的路由格式

场景说明

我在Craft CMS中同时通过routes.php配置路由,以及在模块中通过事件注册了相同的路由,现在需要开发插件按名称获取URL,要把两种方式的路由转换成统一格式(和从配置文件获取的一致)。

路由配置代码

1. routes.php中的配置

return [
  'analytics/<tenantSlug:{slug}>/modules/' => ['route' => 'analytics/modules/list', 'name' => 'listModules']
];

2. 模块中通过事件注册路由

private function attachEventHandlers(): void
{
    Event::on(
        UrlManager::class,
        UrlManager::EVENT_REGISTER_SITE_URL_RULES,
        function(RegisterUrlRulesEvent $event) {
            $event->rules['analytics/<tenantSlug:{slug}>/modules/'] = ['route' => 'analytics/modules/list', 'name' => 'listModules'];
        });
}

获取配置文件路由的方法

从routes.php获取路由很简单,代码如下:

$routes = Craft::$app->getRoutes()->getConfigFileRoutes();
foreach ($routes as $route => $route_settings) {
    return $route;
}

返回结果:

'analytics/<tenantSlug:{slug}>/modules/'

获取模块注册路由遇到的问题

当获取模块中注册的路由时,执行以下代码:

return Craft::dd(Craft::$app->getUrlManager()->rules[0]);

得到的UrlRule对象结构如下:

craft\web\UrlRule#1
(
    [name] => 'listModules'
    [pattern] => '#^analytics/(?P<ac53bbfc2>(?:[\\p{L}\\p{N}\\p{M}\\._\\-]+))/modules$#u'
    [host] => null
    [route] => 'analytics/modules/list'
    [defaults] => []
    [suffix] => null
    [verb] => null
    [mode] => null
    [encodeParams] => true
    [normalizer] => null
    [*:createStatus] => null
    [*:placeholders] => [
        'ac53bbfc2' => 'tenantSlug'
    ]
    [yii\web\UrlRule:_template] => '/analytics/<tenantSlug>/modules/'
    [yii\web\UrlRule:_routeRule] => null
    [yii\web\UrlRule:_paramRules] => [
        'tenantSlug' => '#^(?:[\\p{L}\\p{N}\\p{M}\\._\\-]+)$#u'
    ]
    [yii\web\UrlRule:_routeParams] => []
    [params] => []
)

需要将这个对象转换为和配置文件路由一致的格式。

解决方案

要从UrlRule对象中还原出配置文件风格的路由字符串,可以利用对象的私有属性_template和_paramRules来拼接:

/**
 * 从UrlRule对象中还原配置风格的路由字符串
 * @param \craft\web\UrlRule $urlRule
 * @return string
 */
function getConfigStyleRoute(\craft\web\UrlRule $urlRule): string
{
    // 获取模板路径,去掉开头的斜杠
    $template = ltrim($urlRule->_template, '/');
    
    // 替换占位符为带规则的格式
    foreach ($urlRule->_paramRules as $paramName => $pattern) {
        // 匹配Craft的规则别名,比如{slug}对应正则
        $ruleAlias = match($pattern) {
            '#^(?:[\\p{L}\\p{N}\\p{M}\\._\\-]+)$#u' => '{slug}',
            // 可根据需求添加更多Craft内置规则的匹配
            default => '{any}'
        };
        
        $template = str_replace("<$paramName>", "<$paramName:$ruleAlias>", $template);
    }
    
    // 确保结尾的斜杠和配置文件格式一致
    if (!str_ends_with($template, '/')) {
        $template .= '/';
    }
    
    return $template;
}

// 使用示例
$urlRule = Craft::$app->getUrlManager()->rules[0];
$configStyleRoute = getConfigStyleRoute($urlRule);
// 输出:analytics/<tenantSlug:{slug}>/modules/

说明

  • _template属性存储了不带规则的路由模板,比如/analytics/<tenantSlug>/modules/
  • _paramRules属性存储了每个参数对应的正则规则,我们可以将正则映射回Craft的规则别名(如{slug})
  • 最后调整结尾的斜杠,确保和配置文件中的格式完全匹配

内容的提问来源于stack exchange,提问作者Ross Lote

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 22:27:22