控制器设置Action及自定义URL路由的CMS适配问题咨询
嘿,这个问题我之前碰到过类似的——核心就是你自定义的路由分段$URLSegment/$Name/$Action/$ID和SilverStripe CMS默认的ModelAsController解析逻辑不匹配!CMS父类的getNestedController还是按默认的$URLSegment/$Action/$ID结构去读分段,自然会把第三段当成$ID,直接忽略掉你加的$Name部分。
下面给你几个实用的解决思路,你可以根据自己的业务场景挑合适的:
思路1:调整路由分段顺序(最省心)
如果业务逻辑允许,把$Name移到后面,尽量贴合CMS默认的路由结构,比如改成:
'$URLSegment/$Action/$Name/$ID': 'BaseController'
这样CMS父类处理时,前两段还是它熟悉的$URLSegment/$Action,后面的$Name和$ID你在BaseController里自己处理就行。这个方案最简单,前提是你能接受分段顺序的调整。
思路2:在BaseController里手动修正分段再交父类
要是不能改路由顺序,那就在重写的getNestedController方法里,先把URL分段拆了重新整理,把$Name存起来,再把剩下的分段按CMS预期的格式传给父类。举个代码例子:
class BaseController extends ModelAsController { protected $customName; // 存自定义的Name字段 public function getNestedController($urlSegment) { $segments = explode('/', trim($urlSegment, '/')); // 确认存在$Name分段(也就是第二个位置的分段) if (count($segments) >= 2) { $this->customName = $segments[1]; // 重新组装URL:去掉$Name,剩下的按默认结构传给父类 $adjustedSegments = array_merge([$segments[0]], array_slice($segments, 2)); $newUrlSegment = implode('/', $adjustedSegments); return parent::getNestedController($newUrlSegment); } // 没有$Name的情况,直接走父类逻辑 return parent::getNestedController($urlSegment); } // 后续业务里可以用$this->customName获取这个值 }
这样父类拿到的就是$URLSegment/$Action/$ID格式的分段,就能正确识别子页面了,你需要的$Name也已经存在控制器里随时能用。
思路3:给自定义路由加前缀,隔离CMS默认路由
如果你只是针对特定URL需要这个自定义逻辑,可以给路由加个专属前缀,避免和CMS的默认路由冲突,比如:
'custom-path/$URLSegment/$Name/$Action/$ID': 'BaseController'
这样只有以custom-path/开头的URL才会走你的BaseController,其他页面还是用CMS默认的路由逻辑,从根源上避免分段识别错位的问题。
另外提个小注意:如果你用的是SilverStripe 4及以上版本,路由要确保在app/_config/routes.yml里正确配置,或者在代码里用Router::addRoute()注册,别搞错了注册方式哦。
内容的提问来源于stack exchange,提问作者Rudiger

