Yii validation rules ignores 'on' or 'except'

565 Views Asked by At

I faced with a next problem. I'm trying to validate field in different ways, depening on action: phone is should be unique on user create, and should not on user edit, so:

    public function rules()
{
    return [
        [['owner_id','card_code', 'name', 'phone', 'birthday','language', 'last_ip'], 'required'],
        [['account_id'], 'required', 'on' => 'update'],
        [['account_id'], 'exist', 'skipOnError' => true, 'targetClass' => Accounts::className(), 'targetAttribute' => ['account_id' => 'id'], 'on' => 'update'],

        [['owner_id', 'account_id', 'active', 'last_carwash'], 'integer'],
        [['birthday', 'last_active', 'last_update', 'last_sync'], 'safe'],
        [['car_number', 'role', 'status'], 'string'],
        [['card_code', 'car_number', 'name', 'phone', 'password', 'auth_key', 'language'], 'string', 'max' => 255],
        [['last_ip'], 'ip'],
        [['name'], 'string', 'min' => 5],

        ['password', 'string', 'min' => 6, 'message' => Yii::t('app', 'The password must contain at least 6 symbols.')/*, 'on' => 'create'*/],
        ['password', 'match', 'pattern' => '/[A-z]/', 'message' => Yii::t('app', 'The password must contain at least 1 letter.')/*, 'on' => 'create'*/],
        ['password', 'match', 'pattern' => '/[0-9]/', 'message' => Yii::t('app', 'The password must contain at least 1 number.')/*, 'on' => 'create'*/],
        [['password'], 'required', 'on' => 'create'],
        [['phone'], 'validatePhone', 'except' => 'update'/*, 'skipOnEmpty' => false*/],
        [['email'], 'email'],
        [['email'], 'validateEmail', 'except' => 'update'/*, 'skipOnEmpty' => false*/],
    ];
}

I'm using AJAX validation:

$form = ActiveForm::begin([
        'enableAjaxValidation' => true,
        'validationUrl' => \yii\helpers\Url::to('/user/validation'),
    ]);

Validation actions:

public function validatePhone()
  
  {
        $phone = preg_filter( '/[^0-9]*/','', $this->phone );
        $u = Users::findOne(['phone' => $phone]);
        if($u)
            /*if($this->id != $u->id)*/
                $this->addError('phone', Yii::t('app', 'This phone is already taken.'));
    }
    public function validateEmail()
    {
        $email = $this->email;
        if (!filter_var($email, FILTER_VALIDATE_EMAIL))
            $this->addError('email', Yii::t('app', 'Please, enter correct email'));
    
        $u = Users::findOne(['email' => $email]);
        if($u)
            $this->addError('email', Yii::t('app', 'This email is already taken.'));
    }

In controller actions

   public function actionCreate()
        {
            if ( Yii::$app->request->post() != NULL ) {
            $data = Yii::$app->request->post('Users');
            $model = new Users;
            $model->scenario = 'create';
           ...//lots of a code
            if(!$model->validate()){var_dump($model->errors);exit;}
            $model->save();
             return $this->redirect(['view', 'id' => $model->id]);
        }

    public function actionUpdate($id)
        {
          $model = $this->findModel($id);
          $model->scenario = 'update';
          $model->setScenario('update');// same as ^ , but who knows...
         $data = Yii::$app->request->post();

         if( $data )
         {
        ...//lots of code
           if(!$model->validate()){var_dump($model->errors);exit;}
           $model->save();
             return $this->redirect(['view', 'id' => $model->id]);
          }
         return $this->render('update', [
            'model' => $model,
          ]);
       }

public function actionValidation()
    {
        if (Yii::$app->request->isAjax) {
            Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

            $model = new \app\models\Users();
            if($model->load(Yii::$app->request->post()))
                return \yii\widgets\ActiveForm::validate($model);
        }
        throw new \yii\web\BadRequestHttpException( Yii::t('app', 'Bad request.') );
    }

    protected function findModel($id)
        {
            if (($model = Users::findOne($id)) !== null) {
                return $model;
            }
            throw new NotFoundHttpException(Yii::t('app', 'The requested page does not exist.'));
        }

Scenario:

public function scenarios()
    {
        $scenarios = parent::scenarios();
        $scenarios['create'] = ['account_id', 'card_code', 'name', 'phone', 'email', 'car_number', 'birthday', 'role', 'password'];
        $scenarios['update'] = ['account_id', 'card_code', 'name', 'phone', 'email', 'car_number', 'birthday', 'role', 'password'];
        return $scenarios;
    }

but it doesn't work at all at any forms.

If i delete 'on' => 'create' it works fine, but in ALL forms, what is unwanted. So how can i use validatePhone and validateEmail only in create scenario?

0

There are 0 best solutions below