Search code examples
yii2yii2-modelyii2-validation

Yii2 model custom validate method / function does not work


I want to validate my fine_amount against 2 input date. But it does not return any error. Without validating this method it saved data. I also looked into

Yii2: how to use custom validation function for activeform? but for me no solution.

Below is my code

Controller method

    $model = $this->findModel($id);

    $model->payment_date=date('d-M-Y',strtotime($model->payment_date));
    $model->payment_expected_date=date('d-M-Y',strtotime($model->payment_expected_date));

    if ($model->load(Yii::$app->request->post())) {
        $model->payment_date=date('Ymd',strtotime($model->payment_date));
        $model->payment_expected_date=date('Ymd',strtotime($model->payment_expected_date));

        if($model->validate()){
            $model->save();
            return $this->redirect(['view', 'id' => $model->id]);
        }
        else{
            $model->payment_date=date('d-M-Y',strtotime($model->payment_date));
            $model->payment_expected_date=date('d-M-Y',strtotime($model->payment_expected_date));

            return $this->render('update', [
                'model' => $model,
            ]);
        }
    }

    return $this->render('update', [
        'model' => $model,
    ]);

My Rule

['fine_amount' , 'fine_required'] ,

Validation function

public function fine_required() {
    $this->payment_date = date ( 'Ymd' , strtotime ( $this->payment_date ) );
    $this->payment_expected_date = date ( 'Ymd' , strtotime ( $this->payment_expected_date ) );

    if ( $this->payment_date > $this->payment_expected_date ) {
        if ( $this->fine_amount <= 0 ) {
            $this->addError ( 'fine_amount' , 'Fine Amount Must be add.' );
        }
        return false;
    }
    return true;
}

Solution

  • You need to use conditional validation for your case, use when and whenClient respectively see below add to your rules section and remove any other validations. This will handle frontend and backend both validations

    [ 'fine_amount' , 'required' , 'when' => function($model) {
            if ( $model->payment_date > $model->payment_expected_date ) {
                if ( $model->fine_amount <= 0 ) {
                    return true;
                }
            }
            return false;
        } , 'whenClient' => 'function (attribute, value) {
    
        var d1 = new Date($("#' . Html::getInputId($this, 'payment_date') . '").val());
        var d2 = new Date($("#' . Html::getInputId($this, 'payment_expected_date'). '").val());
        if(d1>d2){
            if(value<=0){
                return true;
            }
        }
        return false;
    }' , 'message' => 'Fine Amount Must be add.' ] ,
    

    EDIT

    Replaced strtolower ( \yii\helpers\StringHelper::basename ( get_class ( $this ) ) ) with Html::getInputId as it is more suitable for this case.