Search code examples
phpyii2postman

How to save registered user in database with yii2?


I try to save a registerd user in the database with an api call.

So I have an model 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]],
        ];
    }

}

and an controller 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];
        }
    }

and urlManager in web.php looks:

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

and databse schema looks:

$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(),
        ]);

But if I try to call the api call in postman:

http://localhost:8080/v1/user/signup with json object:

{
    "username": "example_user",
    "password_hash": "example_password",
    "email": "[email protected]" 
}

I get this error:

 "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\"",

Question: how to resolve this error?


Solution

  • You need to set up validation rules for all attributes that should be populated by load() method. That method only populates attributes that are considered "safe". Safe attributes are those that have at least one validation rule.

    If you really don't want to validate your attributes you can use safe validator. This validator doesn't perform any validation it only serves to mark attribute as "safe".

    But generally speaking it's much better to set up proper validation instead of "accept anything" approach.