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

Yii2中通过API保存注册用户失败,如何解决非空约束错误?

问题描述

尝试通过API调用将注册用户保存到数据库时,触发数据库非空约束错误。调用http://localhost:8080/v1/user/signup接口并传入以下JSON:

{
"username": "example_user",
"password_hash": "example_password",
"email": "gmail@gmail.com"
}

报错信息如下:

{
    "name": "Integrity constraint violation",
    "message": "SQLSTATE[23502]: Not null violation: 7 ERROR:  null value in column \"username\" of relation \"user\" violates not-null constraint\nDETAIL:  Failing row contains (3, null, null, null, null, null, 10, 1710925298, 1710925298, null).\nThe SQL being executed was: INSERT INTO \"user\" (\"status\", \"created_at\", \"updated_at\") VALUES (10, 1710925298, 1710925298) RETURNING \"id\""
}

相关代码及配置如下:

User.php 模型

<?php

namespace app\models;
use Yii;
use yii\base\NotSupportedException;
use yii\behaviors\TimestampBehavior;
use yii\db\ActiveRecord;
use yii\web\IdentityInterface;


class User extends \yii\db\ActiveRecord implements IdentityInterface
{

    const STATUS_DELETED = 0;
    const STATUS_INACTIVE = 9;
    const STATUS_ACTIVE = 10;
 
    public function behaviors()
    {
        return [
            TimestampBehavior::class,
        ];
    }

    public static function tableName()
    {
        return '{{%user}}';
    }


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

}

UserController.php 控制器

<?php
// phpcs:ignoreFile

namespace app\modules\v1\controllers;
use Yii;
use app\models\User;
use yii\rest\ActiveController;
use yii\web\Response;

class UserController extends ActiveController
{
    public $modelClass = 'app\models\User';


    public function actionSignup()
    {
        $user = new User();
        $user->load(Yii::$app->getRequest()->getBodyParams(), '');
        
        if ($user->save()) {
            Yii::$app->response->statusCode = 201;
            return ['status' => 'success', 'data' => 'User registered successfully'];
        } else {
            Yii::$app->response->statusCode = 400;
            return ['status' => 'error', 'data' => $user->errors];
        }
    }
}

web.php 中的 urlManager 配置

'urlManager' => [
    'enablePrettyUrl' => true,
    'showScriptName' => false,
    'rules' =>  ['class' => 'yii\rest\UrlRule', 'controller' => 'v1/user', 'POST' => 'v1/user/signup'],
]

数据库表结构

$this->createTable('{{%user}}', [
    'id' => $this->primaryKey(),
    'username' => $this->string()->notNull()->unique(),
    'auth_key' => $this->string(32)->notNull(),
    'verification_token'=>$this->string()->defaultValue(null),
    'password_hash' => $this->string()->notNull(),
    'password_reset_token' => $this->string()->unique(),
    'email' => $this->string()->notNull()->unique(),
    'status' => $this->smallInteger()->notNull()->defaultValue(10),
    'created_at' => $this->integer()->notNull(),
    'updated_at' => $this->integer()->notNull(),
]);
原因分析
  1. 模型缺少必填字段验证规则:User模型的rules()方法仅定义了status字段的规则,没有包含username、email、password_hash等必填字段的验证,导致load()方法无法将请求参数赋值给模型属性。
  2. auth_key字段未自动生成:数据库要求auth_key为非空字段,但模型中没有处理该字段的自动生成逻辑,保存时该字段为null,触发约束错误。
  3. URL规则配置不规范:原URL规则可能导致请求映射异常,影响参数解析。
解决步骤

1. 完善User模型的验证规则

在rules()方法中添加必填字段的验证规则,确保请求参数能被正确赋值和验证:

public function rules()
{
    return [
        ['status', 'default', 'value' => self::STATUS_ACTIVE],
        ['status', 'in', 'range' => [self::STATUS_ACTIVE, self::STATUS_INACTIVE, self::STATUS_DELETED]],
        // 添加必填字段验证与格式规则
        [['username', 'email', 'password_hash'], 'required'],
        [['username', 'email'], 'string', 'max' => 255],
        [['username', 'email'], 'unique'],
    ];
}

2. 自动生成auth_key字段

在User模型中重写beforeSave()方法,在插入新用户时自动生成随机的auth_key:

public function beforeSave($insert)
{
    if (parent::beforeSave($insert)) {
        if ($insert) {
            // 生成32位随机字符串作为auth_key
            $this->auth_key = Yii::$app->security->generateRandomString();
        }
        return true;
    }
    return false;
}

3. 调整URL规则配置

修改urlManager的规则,确保POST请求正确映射到signup动作:

'urlManager' => [
    'enablePrettyUrl' => true,
    'showScriptName' => false,
    'rules' => [
        'POST v1/user/signup' => 'v1/user/signup',
        ['class' => 'yii\rest\UrlRule', 'controller' => 'v1/user'],
    ],
]

4. 优化控制器参数处理(可选)

可以在保存前显式调用validate()方法,提前获取验证错误(save()方法会自动调用validate(),此步骤为可选):

public function actionSignup()
{
    $user = new User();
    $user->load(Yii::$app->getRequest()->getBodyParams(), '');
    
    if ($user->validate() && $user->save()) {
        Yii::$app->response->statusCode = 201;
        return ['status' => 'success', 'data' => 'User registered successfully'];
    } else {
        Yii::$app->response->statusCode = 400;
        return ['status' => 'error', 'data' => $user->errors];
    }
}

完成以上修改后,重新调用接口即可正常保存用户数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 13:45:53