Yii2 v2模块已加载但所有路由均返回404错误求助
Yii2 V2模块所有端点返回404问题排查与解决
问题背景
项目中新增V2模块(复制V1模块修改而来,V1运行正常),已替换所有V1相关内容并检查大小写正确性。模块在web.php中注册成功,日志显示"ApiV2Module is bootstrapping"且V2模块已加载,但使用Postman测试所有V2端点(如<url>/v2/user/get-level-exp/63)均返回404错误。
相关配置与代码
1. web.php模块注册配置
'bootstrap' => [ 'log', 'v1', 'v2'], 'modules' => [ 'v1' => [ 'class' => api\modules\v1\ApiV1Module::class, 'controllerNamespace' => 'api\modules\v1\controllers', ], 'v2' => [ 'class' => api\modules\v2\ApiV2Module::class, 'controllerNamespace' => 'api\modules\v2\controllers', ], ],
2. web.php URL管理器配置
'urlManager' => [ 'enablePrettyUrl' => true, 'showScriptName' => false, 'rules' => [ ], ],
3. ApiV2Module.php路由规则
public function bootstrap($app) { \Yii::info("ApiV2Module is bootstrapping", __METHOD__); \Yii::info("Incoming request to: " . \Yii::$app->request->url, __METHOD__); $app->getUrlManager()->addRules([ '/v2/user/<id:\d+>' => '/v2/user/index', '/v2/friends/<id:\d+>' => '/v2/friends/index', '/v2/challenge/<id:\d+>' => '/v2/challenge/index', '/v2/challenge/<id:\d+>/<action>' => '/v2/challenge/<action>', '/v2/exercises/<id:\d+>' => '/v2/exercises/index', '/v2/exercises/<id:\d+>/<action>' => '/v2/exercises/<action>', '/v2/notifications/<page:\d+>' => '/v2/notifications/index', '/v2/notifications/<_a>' => '/v2/notifications/<_a>', '/v2/user/goals/<id:\d+>' => '/v2/user/goals', '/v2/user/exp/<id:\d+>' => '/v2/user/exp', ]); }
4. UserController核心代码
<?php namespace api\modules\v2\controllers; use api\components\Controller; use api\modules\v2\models\User\UserInfoModel; use api\modules\v2\models\User\UserUpdateModel; use api\modules\v2\models\User\UserDeleteModel; use api\modules\v2\actions\User\DashboardAction; use api\modules\v2\models\UserGoalsModel; use api\modules\v2\models\UserLevelExpModel; class UserController extends Controller { public function actionIndex($id = null) { \Yii::info("Entering actionIndexV2 with ID: $id", __METHOD__); if ($this->request->isGet) { return $this->processActionModel( new UserInfoModel([ 'user_id' => $id, 'logged_user_id' => \Yii::$app->user->id, ]), ); } else if ($this->request->isPatch) { return $this->processActionModel( new UserUpdateModel([ 'user_id' => \Yii::$app->user->id ]), ); } else if ($this->request->isDelete) { return $this->processActionModel( new UserDeleteModel([ 'user_id' => $id ]), ); } } public function actions() { \Yii::info("Actions method called in UserController V2", __METHOD__); return [ 'dashboard' => DashboardAction::class, ]; } // 获取并更新目标 public function actionGoals($id) { \Yii::info("Entering actionGetGoals with ID: $id", __METHOD__); $model = new UserGoalsModel(['user_id' => $id]); return $this->processActionModel($model); } public function actionUpdateGoals($id) { \Yii::info("Entering actionUpdateGoals with ID: $id", __METHOD__); $model = new UserGoalsModel(['user_id' => $id]); $newGoals = \Yii::$app->request->post('goals'); return $model->updateGoals($newGoals); } // 获取并更新等级与经验 public function actionExp($id) { \Yii::info("Entering actionGetLevelExp with ID: $id", __METHOD__); $model = new UserLevelExpModel(['user_id' => $id]); return $this->processActionModel($model); } public function actionUpdateLevelExp($id) { \Yii::info("Entering actionUpdateLevelExp with ID: $id", __METHOD__); $model = new UserLevelExpModel(['user_id' => $id]); $newLevel = \Yii::$app->request->post('level'); $newExp = \Yii::$app->request->post('exp'); return $model->updateLevelExp($newLevel, $newExp); } }
5. UserLevelExpModel代码
<?php namespace api\modules\v2\models\User; use yii\base\Model; use app\models\User; use yii\web\NotFoundHttpException; class UserLevelExpModel extends Model { public int $user_id; public function process(): mixed { $user = User::findOne($this->user_id); if (!$user) { throw new NotFoundHttpException("User not found"); } return [ 'level' => $user->level, 'exp' => $user->exp, ]; } public function updateLevelExp($newLevel, $newExp): bool { $user = User::findOne($this->user_id); if (!$user) { throw new NotFoundHttpException("User not found"); } $user->level = $newLevel; $user->exp = $newExp; return $user->save(); } }
排查与解决方案
1. 路由规则缺失
测试的/v2/user/get-level-exp/63没有对应的路由规则,当前V2模块仅配置了/v2/user/exp/<id:\d+>对应actionExp,但未添加get-level-exp的映射规则。
- 修复方案:在ApiV2Module的bootstrap方法中新增路由规则:
或直接使用默认路由匹配的端点'/v2/user/get-level-exp/<id:\d+>' => '/v2/user/exp',/v2/user/exp/63(对应actionExp方法)。
2. 路由规则前缀异常
当前路由规则中路径前带了/,可能导致匹配失败,Yii的URL规则不需要开头的/,去掉后匹配更可靠。
- 修复方案:修改所有路由规则,去掉开头的
/,例如:'v2/user/<id:\d+>' => 'v2/user/index', 'v2/user/exp/<id:\d+>' => 'v2/user/exp', // 其他规则同理调整
3. 启用默认路由匹配
如果自定义路由覆盖不全,可在urlManager的rules中添加默认路由规则,确保未匹配到自定义规则的请求能正常解析:
'<module:\w+>/<controller:\w+>/<action:\w+>/<id:\d+>' => '<module>/<controller>/<action>',
4. 验证文件与命名空间一致性
确认api\modules\v2\ApiV2Module类文件存在,且命名空间与文件路径一致;控制器文件需放在api/modules/v2/controllers/目录下,命名空间正确。
5. 开启路由调试日志
在web.php中添加路由调试日志配置,查看请求的路由匹配过程:
'log' => [ 'targets' => [ [ 'class' => 'yii\log\FileTarget', 'levels' => ['info', 'trace'], 'categories' => ['yii\web\UrlManager*'], ], ], ],
通过日志可明确请求是否命中正确的路由规则,定位匹配失败原因。
内容的提问来源于stack exchange,提问作者Julian
相关产品推荐
相关产品推荐

