如何从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
相关产品推荐
相关产品推荐

