Yii2路由规则匹配失败返回404 未校验后续模块路由问题求解
问题根因
Yii2路由规则按从上到下顺序匹配,<controller>这类泛化占位符规则只会校验URL格式是否匹配,不会提前校验对应控制器是否存在。如果把泛化controller规则放在模块规则前面,只要URL格式符合controller规则,就会直接命中,后续解析时发现控制器不存在直接返回404,不会走到后续模块规则。你当前把controller规则全部注释,所以请求http://yii2/post没有对应规则匹配,自然返回404。
解决方案
给泛化controller规则增加matchCallback回调,主动校验对应根控制器是否存在,存在才命中规则,不存在则跳过继续匹配后续模块规则,修改后的完整配置参考如下:
'urlManager' => [ 'enablePrettyUrl' => true, 'showScriptName' => false, 'rules' => [ 'store/upload'=>'store/upload', 'stores'=>'store/index', 'comment/send'=>'comment/send', ['class' => 'yii\rest\UrlRule', 'controller' => 'Api', 'prefix' => 'api'], 'api/<id:\d+>'=>'api/view', [ 'pattern' => 'users', 'route' => 'users/index', 'suffix' => '/', 'normalizer' => false, ], // 根控制器通用规则 增加存在性校验 [ 'pattern' => '<controller>', 'route' => '<controller>/index', 'matchCallback' => function ($rule, $request) { $controllerName = Yii::$app->request->getPathInfo(); $controllerClass = 'app\controllers\\' . ucfirst($controllerName) . 'Controller'; return class_exists($controllerClass); } ], [ 'pattern' => '<controller>/<id:\d+>', 'route' => '<controller>/view', 'matchCallback' => function ($rule, $request) { $pathParts = explode('/', Yii::$app->request->getPathInfo()); $controllerName = $pathParts[0]; $controllerClass = 'app\controllers\\' . ucfirst($controllerName) . 'Controller'; return class_exists($controllerClass); } ], [ 'pattern' => '<controller>/<action>', 'route' => '<controller>/<action>', 'matchCallback' => function ($rule, $request) { $pathParts = explode('/', Yii::$app->request->getPathInfo()); $controllerName = $pathParts[0]; $controllerClass = 'app\controllers\\' . ucfirst($controllerName) . 'Controller'; return class_exists($controllerClass); } ], // 模块相关规则放在后面 '<module>' => '<module>/default/index', '<module>/<id:\d+>' => '<module>/default/view', '<module>/edit/<id:\d+>' => '<module>/default/edit', '<module>/delete/<id:\d+>' => '<module>/default/delete', '<module>/<action>' => '<module>/default/<action>', '<module>/<controller>' => '<module>/<controller>/index', '<module>/<controller>/edit/<id:\d+>' => '<module>/<controller>/edit', '<module>/<controller>/delete/<id:\d+>' => '<module>/<controller>/delete', '<module>/<controller>/<id:\d+>' => '<module>/<controller>/view', '<module>/<controller>/<action>' => '<module>/<controller>/<action>', ], ],
如果你的控制器命名空间不是默认的app\controllers,请替换为实际的命名空间路径即可。
内容的提问来源于stack exchange,提问作者temp_name
相关产品推荐
相关产品推荐

