简体   繁体   English

如何在Yii2中更新用户配置文件期间管理密码

[英]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. 我可以成功添加用户,For Password hashing我正在使用md5()但是当我更新用户时它会给出错误。

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 ie 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 未定义的偏移量:1无法准备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! 谢谢!

User Model 用户模型

public function rules()
{
    return [
        [['firstname', 'lastname', 'username', 'email', 'role', 'group_user','status'], 'required'],
        ['email','email'],
        [['password', 'confirm'], 'required', 'on' => 'create'],

        ['confirm', 'compare', 'compareAttribute' => 'password', 'message'=>"Passwords does not match." ],
        [['firstname', 'lastname', 'username', 'email', 'password', 'confirm', ], 'string', 'max' => 255],
    ];
}

Update Action 更新行动

public function actionUpdate($id)
{
    $model = $this->findModel($id);
    $model->passowrd = '';
    $model->confirm = '';

    if ($model->load(Yii::$app->request->post())) {
        $model->role = $model->role[0]; 
        if (empty($model->password) || empty($model->confirm)) {
            $model->password = $model->getOldAttribute('password');
            $model->confirm = $model->getOldAttribute('confirm');
        }
        if ($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,
        ]);
    }
}

Form 形成

<div class="form-group">
    <?= $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>

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: 最好在你的情况下使用scenarios并使用rules()来满足其他需求,在Users.php模型文件中编写以下代码:

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: 在您的控制器文件中, UsersController.php使用以下代码:

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. 希望这对你有所帮助。

I have my own basic User model i reuse for most projects, which handles updating new password or leaving the previous one if no password is provided by the update form. 我有自己的基本用户模型,我可以重用于大多数项目,如果更新表单没有提供密码,它会处理更新新密码或保留前一个密码。 Also implements IdentityInterface so it can be used for login to the Application. 还实现IdentityInterface以便它可以用于登录到Application。

My basic User model: 我的基本用户模型:

<?php

namespace app\models;

use Yii;
use yii\db\ActiveRecord;
use yii\web\IdentityInterface;

class User extends ActiveRecord implements IdentityInterface {
    const SCENARIO_LOGIN = 'login';
    const SCENARIO_CREATE = 'create';
    const SCENARIO_UPDATE = 'update';

    // We use $hash to save the hashed password we already have saved in the DB
    public $hash;
    public $password_repeat;

    /**
     * @inheritdoc
     */
    public static function tableName() {
        return 'user';
    }

    /**
     * @inheritdoc
     */
    public function scenarios() {
        $scenarios = parent::scenarios();
        $scenarios[self::SCENARIO_LOGIN] = ['user', 'password'];
        $scenarios[self::SCENARIO_CREATE] = ['user', 'password', 'password_repeat', 'email', 'authKey'];
        $scenarios[self::SCENARIO_UPDATE] = ['user', 'password', 'password_repeat', 'email'];
        return $scenarios;
    }

    /**
     * @inheritdoc
     */
    public function rules() {
        return [
            [['user'], 'string', 'max' => 45],

            [['email'], 'string', 'max' => 45],
            [['email'], 'email'],

            [['password', 'password_repeat'], 'string', 'max' => 60],

            [['authKey'], 'string', 'max' => 32],

            [['user', 'password'], 'required', 'on' => self::SCENARIO_LOGIN],
            [['user', 'password', 'password_repeat', 'email'], 'required', 'on' => self::SCENARIO_CREATE],
            [['user', 'email'], 'required', 'on' => self::SCENARIO_UPDATE],

            // Generate a random String with 32 characters to use as AuthKey
            [['authKey'], 'default', 'on' => self::SCENARIO_CREATE, 'value' => Yii::$app->getSecurity()->generateRandomString()],

            [['password'], 'compare', 'on' => self::SCENARIO_CREATE, 'skipOnEmpty' => true],

            [['user'], 'unique'],
        ];
    }

    /**
     * @inheritdoc
     */
    public function attributeLabels() {
        return [
            'id' => 'Id',
            'user' => 'User',
            'password' => 'Password',
            'authKey' => 'AuthKey',
            'email' => 'Email',
        ];
    }

    /**
     * @inheritdoc
     */
    public function beforeSave($insert) {
        if (parent::beforeSave($insert)) {
            if($insert) {
                $this->password = Yii::$app->getSecurity()->generatePasswordHash($this->password);
            }
            else {
                if(strlen($this->password) > 0) {
                    $this->password = Yii::$app->getSecurity()->generatePasswordHash($this->password);
                }
                else {
                    $this->password = $this->hash;
                }
            }
            return true;
        }
        return false;
    }

    /**
     * @inheritdoc
     */
    public function afterFind() {
        $this->hash = $this->password;
        $this->password = '';
        parent::afterFind();
    }

    /**
     * @inheritdoc
     */
    public static function findIdentity($id) {
        return self::findOne($id);
    }

    /**
     * @inheritdoc
     */
    public static function findIdentityByAccessToken($token, $type = null) {
        throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');
    }

    /**
     * @inheritdoc
     */
    public static function findByUsername($username) {
        $model = static::findOne(['user' => $username]);
        return $model;
    }

    /**
     * @inheritdoc
     */
    public function getId() {
        return $this->getPrimaryKey();
    }

    /**
     * @inheritdoc
     */
    public function getAuthKey() {
        return $this->authKey;
    }

    /**
     * @inheritdoc
     */
    public function validateAuthKey($authKey) {
        return $this->authKey === $authKey;
    }

    /**
     * Validates password
     *
     * @param string $password password to validate
     * @return boolean if password provided is valid for current user
     */
    public function validatePassword($password) {
        return Yii::$app->getSecurity()->validatePassword($password, $this->hash);
    }
}

This way you only need to use the corresponding scenario in your create , update and login actions: 这样,您只需在createupdatelogin操作中使用相应的scenario

$model->scenario = User::SCENARIO_LOGIN;
$model->scenario = User::SCENARIO_CREATE;
$model->scenario = User::SCENARIO_UPDATE;

First try this one 首先尝试这个

[['confirm'], 'compare', 'compareAttribute' => 'password','on'=>'create']

if not work then please follow the following steps create your scenario for updation and don't compare password Did you try scenarios.. i will give a simple example for user registration and user login i hope it will help you 如果不行,那么请按照以下步骤创建您的更新方案,不要比较密码您是否尝试过方案..我将给出一个用户注册和用户登录的简单示例我希望它能帮助您

<?php
class User extends Model
{
    public $name;
    public $email;
    public $password;
    public function rules(){
        return [
            [['name','email','password'],'required'],
            ['email','email'],
            [['name', 'email', 'password'], 'required', 'on' => 'register'],
            ];
    }
    public function scenarios()
    {
        $scenarios = parent::scenarios();
        $scenarios['login'] = ['name','password'];//Scenario Values Only Accepted
        return $scenarios;
    }
}
?>

Apply Scenario For Model See the below code, We added two ways of setting the scenario of a model. 应用场景模型请参阅下面的代码,我们添加了两种设置模型场景的方法。 By default, scenario will support the model rules. 默认情况下,方案将支持模型规则。

<?php
class UserController extends Controller
{
    // APPLY SCENARIOS
    // scenario is set as a property
    public function  actionLogin(){
        $model = new User;
        $model->scenario = 'login';
    }
    // scenario is set through configuration
    public function  actionRegister(){
        $model = new User(['scenario' => 'register']);
    }
}
?>

在此输入图像描述 在此输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM