Yii2: how to use custom validation function for activeform?

67,255

Solution 1

Did you read documentation?

According to the above validation steps, an attribute will be validated if and only if it is an active attribute declared in scenarios() and is associated with one or multiple active rules declared in rules().

So your code should looks like:

class SignupForm extends Model
{
    public function rules()
    {
        return [
            ['birth_date', 'checkDateFormat'],

            // other rules
        ];
    }

    public function scenarios()
    {
        $scenarios = [
            'some_scenario' => ['birth_date'],
        ];

        return array_merge(parent::scenarios(), $scenarios);
    }

    public function checkDateFormat($attribute, $params)
    {
        // no real check at the moment to be sure that the error is triggered
        $this->addError($attribute, Yii::t('user', 'You entered an invalid date format.'));
    }
}

And in controller set scenario, example:

$signupForm = new SignupForm(['scenario' => 'some_scenario']);

Solution 2

To make custom validations in yii 2 , you can write custom function in model and assign that function in rule. for eg. I have to apply password criteria in password field then I will write like this in model.

public function rules()
{
    return [
        ['new_password','passwordCriteria'],
    ];
}

public function passwordCriteria()
{
    if(!empty($this->new_password)){
        if(strlen($this->new_password)<8){
            $this->addError('new_password','Password must contains eight letters one digit and one character.');
        }
        else{
            if(!preg_match('/[0-9]/',$this->new_password)){
                $this->addError('new_password','Password must contain one digit.');
            }
            if(!preg_match('/[a-zA-Z]/', $this->new_password)){
                $this->addError('new_password','Password must contain one character.');
            }
        }
    }
}

Solution 3

Try forcing the validation on empty field

['birth_date', 'checkDateFormat', 'skipOnEmpty' => false, 'skipOnError' => false],

Also, make sure you don't assign id to your birth_date field in your view.

If you do have id for your birth_date, you need to specify the selectors

<?= $form->field($model, 'birth_date', ['selectors' => ['input' => '#myBirthDate']])->textInput(['id' => 'myBirthDate']) ?>

Solution 4

You need to trigger $model->validate() somewhere if you are extending from class Model.

Solution 5

I stumbled on this when using the CRUD generator. The generated actionCreate() function doesn't include a model validation call so custom validators never get called. Also, the _form doesn't include and error summary.

So add the error summary to the _form.

<?= $form->errorSummary($model); ?>

...and add the validation call - $model->validate() - to the controller action

public function actionCreate()
{
    $model = new YourModel();

    if ($model->load(Yii::$app->request->post()) && $model->validate()) {...
Share:
67,255

Related videos on Youtube

Luigi Caradonna
Author by

Luigi Caradonna

I currently work for a company where I program a 5 axis CNC machine to engrave, cut and shape marble, granite and other stones, both natural and synthetic. I program both for web and mobile devices (recently) for passion.

Updated on April 17, 2020

Comments

  • Luigi Caradonna
    Luigi Caradonna about 4 years

    In my form's model, I have a custom validation function for a field defined in this way

    class SignupForm extends Model
    {
        public function rules()
        {
            return [
                ['birth_date', 'checkDateFormat'],
    
                // other rules
            ];
        }
    
        public function checkDateFormat($attribute, $params)
        {
            // no real check at the moment to be sure that the error is triggered
            $this->addError($attribute, Yii::t('user', 'You entered an invalid date format.'));
        }
    }
    

    The error message doesn't appear under the field in the form view when I push the submit button, while other rules like the required email and password appear.

    I'm working on the Signup native form, so to be sure that it is not a filed problem, I've set the rule

    ['username', 'checkDateFormat']
    

    and removed all the other rules related to the username field, but the message doesn't appear either for it.

    I've tried passing nothing as parameters to checkDateFormat, I've tried to explicitly pass the field's name to addError()

    $this->addError('username', '....');
    

    but nothing appears.

    Which is the correct way to set a custom validation function?

  • Luigi Caradonna
    Luigi Caradonna over 9 years
    That's not the problem, I've tried to apply the custom validation function to the username field, which is correctly set by Yii itself. The validation doesn't work for that field as well.
  • TomaszKane
    TomaszKane over 9 years
    OK, but did you set scenarios? Without it your custom validator just isn't trigger.
  • robsch
    robsch about 9 years
    That's not true. You need that array only if you declaring the rule on more than one property.
  • trejder
    trejder almost 9 years
    Are you sure, that scenarios has anything to do with this issue? If your solution works, then I'd rather call it a side-effect. There real problem, according to this answer, is to set skipOnEmpty to false for custom validator, because by default it is set to true and that's what is causing it to not be executed. Seems, that scenarios doesn't have much in common with OP's problem.
  • Muhammad Omer Aslam
    Muhammad Omer Aslam about 7 years
    conditional validation does not work in this scenario.
  • Mihai P.
    Mihai P. almost 7 years
    that's my point, that kind of validation would not work right away you have client validation on. You would press the submit button, that validation would not run, the rest of the client validation would do.... exactly what the OP says it sees.
  • Muhammad Omer Aslam
    Muhammad Omer Aslam almost 7 years
    you need to create a standalone validator as yii documentation says, that way you can provide the javascript and model / server side both constraints from one validator class, and it would trigger the same way on front-end with the fields focus out event. but conditional validation is totally different from this scenario.
  • 111
    111 over 6 years
    You're not only wrong, you're authoritatively wrong. It's not necessary to declare a scenario.