
yii2 rest api 中 post 请求数据为空导致数据库插入失败,根本原因是模型缺少验证规则和请求解析配置未生效,需正确配置 json 解析器、定义模型验证规则,并确保控制器支持数据绑定。
yii2 rest api 中 post 请求数据为空导致数据库插入失败,根本原因是模型缺少验证规则和请求解析配置未生效,需正确配置 json 解析器、定义模型验证规则,并确保控制器支持数据绑定。
在 Yii2 构建 RESTful API 时,POST 请求无法将 JSON 数据正确绑定到模型(如 Country),常表现为:
- 数据库报错
Field 'code' doesn't have a default value; - 日志中显示
$_POST = [],说明原始表单数据未被解析; - 实际发送的 JSON 被忽略,模型属性未赋值,验证与保存均失败。
这并非路由或控制器配置错误,而是 Yii2 默认不自动解析 JSON 请求体为模型属性,必须显式启用并配合模型层约束才能完成完整的数据流:HTTP Request (JSON) → Request Parser → Model Load → Validation → Save
✅ 正确配置步骤
1. 确保 request 组件已启用 JSON 解析器(您已正确配置 ✅)
// config/web.php
'components' => [
'request' => [
'parsers' => [
'application/json' => 'yii\web\JsonParser',
],
],
// ...
],
⚠️ 注意:该配置必须位于 components 下的 request 项中,且 JsonParser 是唯一能将 application/json 请求体转为 PHP 数组的内置解析器。
2. 在模型中定义验证规则(关键修复!)
仅声明 ActiveRecord 不足以支持 REST 场景下的安全数据绑定。必须重写 rules() 方法,明确指定哪些字段是必填、可选或需类型校验:
<?php // app/models/Country.php
namespace app\models;
use yii\db\ActiveRecord;
class Country extends ActiveRecord
{
public function rules()
{
return [
[['code', 'name'], 'required'], // code 和 name 为必填(对应报错字段)
[['population'], 'integer', 'min' => 0], // population 为整数且非负
[['code'], 'string', 'max' => 2], // 符合典型国家编码长度(如 'CN')
[['name'], 'string', 'max' => 128],
];
}
}
? 为什么必须加
rules()?
Yii2 的ActiveController::actionCreate()内部调用$model->load($request->getBodyParams(), '')—— 该方法仅当存在对应验证规则时才允许属性批量赋值(受safe场景控制)。无rules()时,load()返回false,所有字段保持空值,最终触发数据库NOT NULL约束失败。
3. 验证控制器是否使用标准行为(您已正确继承 ✅)
// app/controllers/CountryController.php
namespace app\controllers;
use yii\rest\ActiveController;
class CountryController extends ActiveController
{
public $modelClass = 'app\models\Country';
}
ActiveController 默认启用 CreateAction,其内部已调用 load() + validate() + save() 流程,无需额外修改。
4. 发送符合规范的 CURL 请求(注意 URL 一致性)
您的原始请求 URL 为 /countries/,但 urlManager 中注册的是 country(单数):
'rules' => [
['class' => 'yii\rest\UrlRule', 'controller' => 'country'],
],
✅ 正确请求应使用复数形式(Yii REST UrlRule 默认复数化):
curl -i \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-X POST "http://XX.X.X.12:XX90/countries/" \
-d '{"code": "TEST", "name": "TestCountry", "population": 0}'
? 提示:
population: 01在 JSON 中会被解析为整数1(前导零无效),建议统一写为0或1。
? 验证是否生效
在 CountryController 中临时添加调试日志:
public function actionCreate()
{
\Yii::info('Raw body: ' . \Yii::$app->request->getRawBody(), __CLASS__);
\Yii::info('Parsed body: ' . json_encode(\Yii::$app->request->getBodyParams()), __CLASS__);
return parent::actionCreate();
}
成功时日志应显示:
Raw body: {"code": "TEST", "name": "TestCountry", "population": 0}
Parsed body: {"code":"TEST","name":"TestCountry","population":0}
⚠️ 常见误区总结
- ❌ 误以为
ActiveRecord自动支持 REST 参数绑定 —— 必须定义rules()启用安全赋值; - ❌ 忽略
parsers配置位置(必须在components.request.parsers,而非其他层级); - ❌ 使用
$_POST检查 JSON 请求 —— JSON 不填充$_POST,应始终用\Yii::$app->request->getBodyParams(); - ❌ 表结构
NOT NULL字段未在模型中设为required—— 导致验证跳过,直接抛出 SQL 错误。
完成以上配置后,POST /countries/ 即可正常创建记录,响应 201 Created 并返回新资源对象。这是 Yii2 REST API 开发中模型层与请求解析协同工作的标准实践。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











