Validation yii2关于唯一属性的更新操作

Validation yii2关于唯一属性的更新操作,validation,yii2,unique,Validation,Yii2,Unique,在用户模型中,我有以下规则 [['username', 'email'], 'unique'], 我想做的是,在新用户创建期间,在更新时(当用户输入另一个用户名或电子邮件以检查其是否唯一时),使此规则可用。但如果我在当前用户模型中不更改用户名(在更新操作中),即使用户不编辑当前用户名和电子邮件,只保存填写的表单(使用当前值),也会出现错误“用户名不唯一” 例如,您的用户名是:user1。您打开了更新操作并仅更改了密码。在这种情况下,我的配置给user1的消息不是唯一的。另一种情况是,您将use

在用户模型中,我有以下规则

[['username', 'email'], 'unique'],
我想做的是,在新用户创建期间,在更新时(当用户输入另一个用户名或电子邮件以检查其是否唯一时),使此规则可用。但如果我在当前用户模型中不更改用户名(在更新操作中),即使用户不编辑当前用户名和电子邮件,只保存填写的表单(使用当前值),也会出现错误“用户名不唯一”

例如,您的用户名是:user1。您打开了更新操作并仅更改了密码。在这种情况下,我的配置给user1的消息不是唯一的。另一种情况是,您将username更改为:user2,它就可以正常工作了

以下是行动代码:

public function actionMe()
{
    $data["model"] = $model = $this->findModel(Yii::$app->user->id);

    if ($model->load(Yii::$app->request->post())) {
        if (trim($model->password) != "")
            $model->setPassword($model->password);
        if ($model->validate() && $model->save())
            return $this->redirect(['site/index']);
    }
    return $this->render('me', $data);
}

如何防止这种行为?

您可以通过两种方式来做到这一点:第一种是从Yii2初学者工具包中获得的。在这里,您可以将这些添加到您的规则中。并将下面的函数添加到用户表单的末尾

[ 'username', 'unique', 'targetClass' => User::className(), 'filter' => function ($query) {
                if (!$this->getModel()->isNewRecord) {
                    $query->andWhere(['not', ['id'=>$this->getModel()->id]]);
                }
            }],



 /**
     * @return app/models/User
     */
    public function getModel()
    {
        if (!$this->model) {
            $this->model = new User();
        }
        return $this->model;
    }
第二种方法是创建自己的验证器,并在更新场景中使用它。 例如:

[['username', 'email'], 'myUniqueValidator','on'=>'update'],

 public function myUniqueValidator($attribute,$params){
        if(!$this->hasErrors()){
            if(User::find()->where([$attribute=>$this->$attribute])->andWhere(['<>','id',Yii::$app->user->id])){

             }

        }
    }

我为更新用户数据创建单独的模型,并在更新模型中创建如下规则:

        ['username', 'trim'],
        ['username', 'required'],
        [
          'username',
          'unique',
          'targetClass' => '\frontend\models\Customer',
          'message' => Yii::t('app', 'This username has already been taken.'),
          'when' => function ($model){
              return $model->username != Yii::$app->user->identity->username;
          }
        ],
        ['username', 'string', 'min' => 2, 'max' => 255],

        ['email', 'trim'],
        ['email', 'required'],
        ['email', 'email'],
        ['email', 'string', 'max' => 255],
        [
          'email',
          'unique',
          'targetClass' => '\frontend\models\Customer',
          'message' => Yii::t('app','This email address has already been taken.'),
          'when' => function ($model){
              return $model->email != Yii::$app->user->identity->email;
          }
        ],

        //['password', 'required', 'skipOnEmpty' => true],
        ['password', 'string', 'min' => 6],

我试过你的案子,但没有得到同样的结果。此外,我的yii2版本是
2.0.11.2
。您使用的是哪个版本的yii2?我认为这与版本无关,我们有相同的verisonIt没有任何意义。你能列出你的模型的规则吗?那些规则很简单,就像字符串一样,没有任何场景
        ['username', 'trim'],
        ['username', 'required'],
        [
          'username',
          'unique',
          'targetClass' => '\frontend\models\Customer',
          'message' => Yii::t('app', 'This username has already been taken.'),
          'when' => function ($model){
              return $model->username != Yii::$app->user->identity->username;
          }
        ],
        ['username', 'string', 'min' => 2, 'max' => 255],

        ['email', 'trim'],
        ['email', 'required'],
        ['email', 'email'],
        ['email', 'string', 'max' => 255],
        [
          'email',
          'unique',
          'targetClass' => '\frontend\models\Customer',
          'message' => Yii::t('app','This email address has already been taken.'),
          'when' => function ($model){
              return $model->email != Yii::$app->user->identity->email;
          }
        ],

        //['password', 'required', 'skipOnEmpty' => true],
        ['password', 'string', 'min' => 6],