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

时间:2017-01-12 11:15:12

标签: php model-view-controller yii2 yii2-advanced-app yii2-model

我可以成功添加用户,对于密码哈希我正在使用md5()但是当我更新用户时它会出错。

以下是模型规则:

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],
    ];
}

在表单中,即View,我使用以下代码:

<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>

在控制器中我使用以下代码:

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

我收到错误:

  

未定义的偏移量:1无法准备SQL:UPDATE xbox_user SET   password =:qp0,role =:qp1,modified =:qp2,status =:qp3 WHERE   id =:QP4

任何人都可以告诉我应该在那里修改哪些代码?

谢谢!

4 个答案:

答案 0 :(得分:2)

用户模型

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],
    ];
}

更新操作

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

<强>表格

<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>

答案 1 :(得分:2)

最好在你的情况下使用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],
    ];
}

在您的视图文件中,使用以下代码:

<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>

并在控制器文件中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,
          ]);
      }
    }

使用此代码,您不会在更新时收到所需密码的错误。如果您填写密码,则将运行确认密码和必需的密码。 希望这对你有所帮助。

答案 2 :(得分:1)

我有自己的基本用户模型,我会重复使用大多数项目,如果更新表单没有提供密码,它会处理更新新密码或保留前一个密码。还实现IdentityInterface,以便它可以用于登录应用程序。

我的基本用户模型:

<?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);
    }
}

这样您只需在scenariocreateupdate操作中使用相应的login

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

答案 3 :(得分:0)

首先试试这个

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

如果不起作用,请按照以下步骤创建更新方案,不要比较密码 您是否尝试过方案..我将给出一个用户注册和用户登录的简单示例,希望它能为您提供帮助

<?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;
    }
}
?>

为模型应用方案 请参阅下面的代码,我们添加了两种设置模型场景的方法。默认情况下,方案将支持模型规则。

<?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']);
    }
}
?>

enter image description here enter image description here