Yii RESTful 接口90%报错源于路由或响应格式未对齐,需优先检查urlManager规则顺序(rest UrlRule置顶)、Web服务器重写配置及on beforeSend中是否错误覆盖statusCode。

Yii RESTful 接口报错,90% 是路由或响应格式没对齐,不是代码逻辑问题。 先别急着改控制器,重点查 urlManager 配置和 response 的 on beforeSend 行为是否冲突。
405 Method Not Allowed 的真实原因在 UrlRule 顺序里
看到 "Method Not Allowed. This url can only handle the following request methods: GET, HEAD." 不代表你没写 PUT 或 DELETE 动作 —— 很可能是 yii\rest\UrlRule 根本没生效,被前面的老式规则劫持了。
- 检查
config/web.php中'urlManager' => ['rules' => [...]]的数组顺序:把['class' => 'yii\rest\UrlRule', ...]放到最前面,删掉类似'<controller:>/<id:>' => '<controller>/view'</controller></id:></controller:>这类通用匹配规则 -
yii\rest\UrlRule默认只对index、view、create、update、delete等动作启用对应 HTTP 方法,不自动支持自定义动作(如actionPublish),需显式配置'extraPatterns' - 如果用了
'enableStrictParsing' => true,但请求路径末尾多了一个/(比如/news/123/),也会 fallback 到老规则,触发 405
404 Not Found 时先确认 URLManager 是否识别了 controller
执行 curl -i http://your.app/country 返回 Apache/Nginx 原生 404(不是 Yii 的 JSON 错误),说明请求根本没进 Yii —— urlManager 没匹配上任何规则,或 Web 服务器未正确转发 PATH_INFO。
- 确保
urlManager中启用了'enablePrettyUrl' => true,且 Web 服务器已配好重写(Apache 要.htaccess,Nginx 要try_files $uri $uri/ /index.php?$args) -
yii\rest\UrlRule的'controller' => ['country']表示允许/country和/country/123,但不会覆盖/country/index这种写法;后者需额外加'extraPatterns'或禁用 strict parsing - 控制器类名必须是
CountryController,命名空间要对(如api\controllers\CountryController),且继承yii\rest\ActiveController或手动实现动作
异常返回 JSON 格式混乱?别动 on beforeSend 里改 statusCode
你写了 'on beforeSend' => function ($event) { ... $response->statusCode = 200; },这会让所有错误(400/401/500)都变成 200 OK,前端无法靠状态码判断失败类型,且破坏 REST 语义。
- 统一错误结构应该用
yii\web\ErrorAction+ 自定义errorHandler,而不是在on beforeSend里硬编码success字段 - 正确做法是在
config/main.php中配置:'errorHandler' => ['errorAction' => 'site/error'],然后在SiteController::actionError()里根据Yii::$app->errorHandler->exception构造标准 JSON,保留原始$response->statusCode - 若坚持用
on beforeSend,至少加判断:if (!$response->isSuccessful) { $response->data = ['status' => 0, 'error_code' => $response->statusCode, 'message' => $response->statusText]; },且不要覆盖statusCode
POST/PUT 提交 JSON 数据却拿不到参数?检查 request->parsers
发 Content-Type: application/json 但 Yii::$app->request->post() 或 $model->load() 为空,大概率是 JSON 解析器没注册。
- 必须在
components中配置:'request' => ['parsers' => ['application/json' => 'yii\web\JsonParser']] -
JsonParser只解析顶层 JSON 对象,不支持嵌套数组直接绑定到模型属性;若传的是{"country": {"name": "CN"}},需用$model->load(Yii::$app->request->getBodyParams(), 'country') - 调试时可用
Yii::$app->request->getRawBody()看原始内容,确认是不是前端发错了格式(比如多包了一层{"data": {...}})
真正卡住的点往往不在控制器里,而在 urlManager 规则顺序、Web 服务器重写配置、或 response 的 on beforeSend 暴力统一状态码 —— 这三处改错一个,就能省掉半天日志排查。


















