Search code examples
phpmodel-view-controlleryii2yii2-advanced-appyii2-model

How to manage password during update user profile in Yii2


I can add user successfully, For Password hashing I am using md5() But when I update user it is giving an error.

Here are the model rules:

public function rules()
{
    return [
        [['firstname', 'lastname', 'username', 'email', 'role', 'group_user','status'], 'required'],
        ['email','email'],
        [['confirm'], 'compare', 'compareAttribute' => 'password','on'=>'create'],
        [['firstname', 'lastname', 'username', 'email', 'password', 'confirm', ], 'string', 'max' => 255],
    ];
}

In the form i.e. View, I am using following code:

<div class="form-group">
<?php
    if($case == 'create') { //this condition called when create user 
        echo $form->field($model, 'password')->passwordInput([
            'maxlength' => true,
            'placeholder' => 'Enter the Password',
        ]);
    }
    else { // during update
        echo $form->field($model, 'password')->passwordInput([
            'maxlength' => true,
            'placeholder' => 'Enter the Password',
            'value' => '',
        ]);
    }
?>
</div>

<div class="form-group">
    <?= $form->field($model, 'confirm')->passwordInput([
        'maxlength' => true,
        'placeholder' => 'Confirm Password',
    ]) ?>   
</div>

and in controller I am using following code:

public function actionUpdate($id)
{
    $model = $this->findModel($id);
    $case = "update";
    if ($model->load(Yii::$app->request->post())) {
        $model->save();
        return $this->redirect(['view', 'id' => $model->id]);
    }
    else {
        return $this->render('update', [
            'model' => $model,
            'all_users_array' => $all_users_array,
            'all_groups_array' => $all_groups_array,
            'case' => $case,
        ]);
    }
}

I am getting the error:

Undefined offset: 1 Failed to prepare SQL: UPDATE xbox_user SET password=:qp0, role=:qp1, modified=:qp2, status=:qp3 WHERE id=:qp4

Can anyone please let me what code should be modified there?

Thank you!


Solution

  • It is better to use scenarios in your case and use rules() too for other requirements, In Users.php model file write the following code:

    public function scenarios(){
      $scenarios = parent::scenarios();
      $scenarios['create'] = ['firstname', 'lastname', 'username', 'email', 'role', 'group_user','status', 'password','confirm'];
      $scenarios['update'] = ['firstname', 'lastname', 'username', 'email', 'role', 'group_user','status'];
      return $scenarios;
    }
    
    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['firstname', 'lastname', 'username', 'email', 'role', 'group_user','status', 'password','confirm'], 'required'],
            ['email', 'filter', 'filter' => 'trim'],
            ['email', 'unique' ],
            ['email', 'unique' ,'targetAttribute' => 'email'],
            ['email', 'required'],
            ['email', 'email'],
            ['email', 'unique', 'targetClass' => '\common\models\Users', 'message' => 'This email address has already been taken.'],
            ['confirm', 'compare', 'compareAttribute'=>'password', 'message'=>"Passwords does not match." ],
            [['firstname', 'lastname', 'username', 'email', 'password', 'confirm', ], 'string', 'max' => 255],
        ];
    }
    

    In your views file use the following code:

    <div class="form-group">
     <?php
      if($case == 'create'){
        echo $form->field($model, 'password')->passwordInput(['maxlength' => true,'placeholder'=>'Enter the Password']);
      }
      else{
        echo $form->field($model, 'password')->passwordInput(['maxlength' => true,'placeholder'=>'Enter the Password']);
     }
    ?>   
    </div>
    <div class="form-group">
        <?= $form->field($model, 'confirm')->passwordInput(['maxlength' =>true,'placeholder'=>'Confirm Password']) ?>   
     </div>
    

    and in your controller file, UsersController.php use the following code:

    public function actionUpdate($id)
    {
      $model = $this->findModel($id);
    
      $model->scenario = 'update'; // calling scenario of update
      if ($model->load(Yii::$app->request->post())) {
    
            $req_array = yii::$app->request->post();
            $role  = $req_array['Users']['role'][0];
    
            $model->role = $role;
            if($req_array['Users']['password'] !== $req_array['Users']['confirm'])
            {
              $model->addError('confirm','Password and Confirm should be same.');
              $model->password = $req_array['Users']['password'];
              $model->confirm = $req_array['Users']['confirm'];
              return $this->render('update', [
                  'model' => $model,
                  'all_users_array'=>$all_users_array,
                  'all_groups_array'=>$all_groups_array,
                  'case'=>$case,
              ]);
            }
            elseif( ($req_array['Users']['password'] == $req_array['Users']['confirm']) && (!empty($req_array['Users']['password'])))
            {
              $model->password = MD5($req_array['Users']['password']);
              $model->save();
              return $this->redirect(['view', 'id' => $model->id]);
            }
            else
            {
    
              $model->save();
              return $this->redirect(['view', 'id' => $model->id]);
            }
          } else {
              $model->password = '';
              return $this->render('update', [
                  'model' => $model,
                  'all_users_array'=>$all_users_array,
                  'all_groups_array'=>$all_groups_array,
                  'case'=>$case,
              ]);
          }
        }
    

    Using this code, you will not get error of required password in update, In case if you fill the password then process of confirm password and required will be run. Hope this helps for you.