You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Yii2 ActiveController的REST接口新增/修改记录时无法接收输入数据

问题简述

我开发的Yii 2应用可正常响应获取数据的REST请求(如GET请求),但在尝试创建、修改记录(即使用POST、PUT等HTTP动词)时完全失败,提交的参数被完全忽略。


问题复现过程

  • 基于*Yii 2 Advanced Project Template(Yii2高级项目模板)*创建空白Yii 2项目,执行命令如下:
composer create-project --prefer-dist yiisoft/yii2-app-advanced yii-application
php init
php yii migrate
  • 参照官方文档为已存在的User模型创建REST风格的UserController:
namespace app\controllers;
use yii\rest\ActiveController;

class UserController extends ActiveController
{
    public $modelClass = 'app\models\User';
}
  • 配置URL规则:
'urlManager' => [
    'enablePrettyUrl' => true,
    'enableStrictParsing' => true,
    'showScriptName' => false,
    'rules' => [
        ['class' => 'yii\rest\UrlRule', 'controller' => 'user'],
    ],
]
  • 开启JSON输入解析:
'request' => [
    'parsers' => [
        'application/json' => 'yii\web\JsonParser',
    ]
]

异常表现

  • GET /users、GET /users/12这类读数据请求可被正确处理。
  • 首次执行如下curl命令提交创建用户请求时,提交的JSON参数{"username": "example", "email": "user@example.com"}被完全忽略,创建出的用户username和email字段均为空值:
curl -i -H "Accept:application/json" -H "Content-Type:application/json" \
    -XPOST "http://localhost/users" \
    -d '{"username": "example", "email": "user@example.com"}'
  • 第二次及后续执行上述curl命令时,抛出*Integrity constraint violation(完整性约束违反)*异常:

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '' for key 'username'
The SQL being executed was: INSERT INTO user (status, created_at, updated_at) VALUES (9, 1654291700, 1654291700)

  • 换用URL编码格式提交数据创建记录,问题依然存在:
    测试截图

问题原因

问题出在Yii2高级项目模板自带的common\models\User模型验证规则配置上。
Yii2的ActiveController处理POST/PUT等写请求时,会调用模型的load()方法将请求参数批量赋值给模型属性。Yii2块赋值机制有明确安全限制:仅当前模型场景下配置了对应验证规则、被标记为安全(safe)的属性,才允许被块赋值接收,未配置验证规则的属性会被直接过滤。
高级模板默认生成的User模型,仅为status字段配置了验证规则,username、email等字段无任何验证规则,不属于安全属性,因此请求提交的这类参数会被全部过滤,最终生成的INSERT语句仅包含有默认值、自动赋值的status、created_at、updated_at字段,提交的用户名、邮箱参数完全不会进入SQL执行逻辑。

修复方法

给User模型补充对应字段的验证规则,把需要通过REST接口批量赋值的字段标记为安全即可,示例配置如下:

public function rules()
{
    return [
        [['username', 'email'], 'required'],
        [['username', 'email'], 'string', 'max' => 255],
        ['username', 'unique'],
        ['email', 'email'],
        ['status', 'default', 'value' => self::STATUS_INACTIVE],
        ['status', 'in', 'range' => [self::STATUS_ACTIVE, self::STATUS_INACTIVE, self::STATUS_DELETED]],
    ];
}

如果不需要做严格的格式校验,也可以直接给对应字段加safe标记,允许块赋值:

public function rules()
{
    return [
        [['username', 'email', 'password_hash'], 'safe'],
        ['status', 'default', 'value' => self::STATUS_INACTIVE],
        ['status', 'in', 'range' => [self::STATUS_ACTIVE, self::STATUS_INACTIVE, self::STATUS_DELETED]],
    ];
}

修改完成后重新发起POST请求,参数即可正常被接收,不会再出现空值和唯一键冲突问题。


内容的提问来源于stack exchange,提问作者trejder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 08:12:31