Yii2框架project_id非空约束校验失效问题求助
Yii2框架中project_id非空约束校验失效问题解决
错误信息
Integrity constraint violation – yii\db\IntegrityException SQLSTATE[23502]: Not null violation: 7 ERROR: null value in column "project_id" violates not-null constraint DETAIL: Failing row contains (853322, 395, 4, 2023, 5245.50, 1, null). The SQL being executed was: INSERT INTO "db"."budget_report_by_project" ("month", "year", "category_id", "currency_id", "project_id", "value") VALUES (4, 2023, 395, 1, NULL, '5245.5') RETURNING "id" Error Info: Array ( [0] => 23502 [1] => 7 [2] => ERROR: null value in column "project_id" violates not-null constraint DETAIL: Failing row contains (853322, 395, 4, 2023, 5245.50, 1, null). ) 1. in /var/www/internal_system/vendor/yiisoft/yii2/db/Schema.php at line 676 2. in /var/www/internal_system/vendor/yiisoft/yii2/db/Command.php at line 1307– yii\db\Schema::convertException(PDOException, 'INSERT INTO "db"."budget_r...') 3. in /var/www/internal_system/vendor/yiisoft/yii2/db/Command.php at line 1168– yii\db\Command::internalExecute('INSERT INTO "db"."budget_r...') 4. in /var/www/internal_system/vendor/yiisoft/yii2/db/Command.php at line 424– yii\db\Command::queryInternal('fetch', null) 5. in /var/www/internal_system/vendor/yiisoft/yii2/db/pgsql/Schema.php at line 646– yii\db\Command::queryOne() 6. in /var/www/internal_system/vendor/yiisoft/yii2/db/ActiveRecord.php at line 604– yii\db\pgsql\Schema::insert('db.budget_report_by_projec...', ['month' => 4, 'year' => 2023, 'category_id' => 395, 'currency_id' => 1, ...]) 7. in /var/www/internal_system/vendor/yiisoft/yii2/db/ActiveRecord.php at line 570– yii\db\ActiveRecord::insertInternal(null) 8. in /var/www/internal_system/vendor/yiisoft/yii2/db/BaseActiveRecord.php at line 676– yii\db\ActiveRecord::insert(true, null) 9. in /var/www/internal_system/models/BudgetReportProject.php at line 463– yii\db\BaseActiveRecord::save()
相关代码
$budgetItem->category_id = $item['category_id']; $budgetItem->currency_id = $item['currency_id']; $budgetItem->project_id = $item['project_id']; $budgetItem->value = $item['value']; if (!is_null($budgetItem->project_id)) { if (!$budgetItem->save()) { $result['error'] = $budgetItem->getErrorMessge(); return $result; } } unset($budgetItem);
问题说明
已添加!is_null($budgetItem->project_id)校验逻辑,期望project_id为null时跳过插入操作,但校验失效,project_id为null时仍触发数据库插入,触发非空约束报错。
解决方案
1. 替换为更严谨的判断逻辑
is_null()仅对严格的null值生效,如果$item['project_id']是空字符串''、数字0等空值,is_null()会返回false导致校验通过。根据project_id的数据类型调整判断:
// 针对字符串类型ID:排除null和空字符串 if ($budgetItem->project_id !== null && $budgetItem->project_id !== '') { // 执行save逻辑 } // 针对数字类型ID:排除null和非正整数 if ($budgetItem->project_id !== null && $budgetItem->project_id > 0) { // 执行save逻辑 }
2. 调试确认属性真实值
在判断前添加调试代码,确认$budgetItem->project_id的实际类型和值:
$budgetItem->project_id = $item['project_id']; // 输出真实值和类型 var_dump($budgetItem->project_id); var_dump(gettype($budgetItem->project_id)); die;
根据输出结果调整判断逻辑,比如实际值是空字符串,就需要加入空字符串的判断。
3. 检查模型与赋值逻辑
- 确认
BudgetReportProject模型中project_id是否设置了默认值,若模型属性默认值覆盖了赋值的null值,会导致校验失效。 - 排查代码中是否存在其他修改
$budgetItem->project_id的逻辑,比如在判断前/后被二次赋值。
4. 结合模型验证增强防护
在BudgetReportProject模型的rules()方法中添加非空验证,即使前置判断失效,模型验证也会阻止插入:
public function rules() { return [ // 其他验证规则 ['project_id', 'required', 'message' => 'project_id不能为空'], // 仅在插入场景验证可添加:['project_id', 'required', 'on' => 'insert'], ]; }
调用save()时会自动执行验证,也可以手动调用validate()提前校验:
if (!is_null($budgetItem->project_id)) { if (!$budgetItem->validate() || !$budgetItem->save(false)) { $result['error'] = $budgetItem->getErrorSummary(true); return $result; } }
内容的提问来源于stack exchange,提问作者Mikel
相关产品推荐
相关产品推荐

