Yii2中PUT/PATCH请求失败主因是未在ActiveController中声明$verbs支持及未配置JsonParser解析JSON请求体,需显式设置update动作为['PUT','PATCH','OPTIONS']并配置request组件的parsers。

PUT 请求 405 或返回空响应?检查 $verbs 和路由是否支持
Yii2 的 yii\rest\ActiveController 默认只注册 GET/POST/DELETE,PUT 和 PATCH 不会自动启用。浏览器或客户端发 PUT /users/123 时若没声明支持,Nginx/Apache 可能直接返回 405,或者 Yii 路由根本没匹配到动作,导致 404 或空白响应。
必须在控制器中显式声明:
public $verbs = [
'view' => ['GET', 'HEAD', 'OPTIONS'],
'update' => ['PUT', 'PATCH', 'OPTIONS'], // 关键:加上 PUT 和 PATCH
];
-
update动作对应PUT /resources/{id}(全量更新)和PATCH /resources/{id}(局部更新) - 如果只允许 PATCH,就删掉
PUT;但别漏OPTIONS,否则跨域预检失败 - 确保
urlManager的'enableStrictParsing' => true已开启,否则/users/123可能被误判为不匹配规则
提交 JSON 数据却提示 “Missing required parameters”?JsonParser 没配对
前端用 fetch 或 axios 发 PUT 带 JSON body(如 {"name":"Alice"}),但 Yii2 默认不解析 application/json 类型的请求体——它还在等 $_POST,自然报参数缺失。
在 config/web.php 或模块配置里补上:
'components' => [
'request' => [
'parsers' => [
'application/json' => 'yii\web\JsonParser',
],
],
],
- 这个配置必须作用于处理该请求的 application 或 module 级别,不是全局写一次就完事
- 如果用了子模块(如
api/v1),得在api/modules/v1/Module.php里重写bootstrap()或覆盖request组件 - 验证是否生效:在
update方法开头加var_dump(Yii::$app->request->getBodyParams());,有数据才说明解析成功
更新后字段没变?load() 失败或模型规则拦住了
ActiveController::update() 内部调用 $model->load($data, ''),但默认只加载 rules() 中标记为 safe 的属性。比如 email 字段没加 ['email', 'safe'],即使 JSON 里传了也不会赋值。
- 要么在模型
rules()中明确把要更新的字段设为safe:['name', 'email', 'status', 'safe'] - 要么改用
$model->load($data, '')的第二个参数为空字符串,绕过场景限制(但需自行校验) - 注意主键字段(如
id)通常不在safe列表里,这是对的——你不该允许客户端改 ID - 如果模型主键不是
id(比如是uid),findModel()必须重写,否则update根本查不到原记录
想支持 PATCH 局部更新,但所有字段都被清空?scenarios() 和 fields() 要配合用
Yii2 默认把 PATCH 当作 update 处理,但不会自动过滤未传字段。如果你没控制好可赋值字段范围,load() 可能把没传的字段设为 null 或空字符串。
- 在模型里定义
scenarios(),例如:public function scenarios() { return ['patch' => ['name', 'email'] + parent::scenarios()['default']; } - 然后在控制器里重写
update(),手动指定场景:$model->load($data, 'patch') - 同时确保
fields()返回的字段和scenarios()一致,避免敏感字段意外暴露(比如password_hash不在patch场景里就不该出现在fields()中) - 别依赖
actions()返回的默认行为做复杂逻辑,PATCH 的语义是“部分修改”,必须自己把控字段边界
JsonParser 配置作用域和 $verbs 对 update 的显式声明——这两处一漏,整个 PUT/PATCH 流程就卡在第一层,连模型层都进不去。


















