Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Yii2: safe validator on condition

Tags:

jquery

php

yii2

I am trying to use this validation rule in my model, but it's not working.

I mean it always remains safe even if select other option.

[['dhanwantri_bill_number'], 'safe', 
    'when' => function($model) {
        return $model->bill_type =='d';                 
    },
    'whenClient' => "function (attribute, value) {
                         return $('#opdtestbill-bill_type').val() == 'd';
                     }"
],

Am I doing anything wrong? is there any alternative solution to achieve the same.

Thanks.

Rule for bill_type is like

[['bill_type'], 'string', 'max' => 20],
[['bill_type','test_name','date'], 'required'],

Edit safe attribute public properties as per doc

$when - callable - A PHP callable whose return value determines whether this validator should be applied. yii\validators\Validator

$whenClient - string - A JavaScript function name whose return value determines whether this validator should be applied on the client side. yii\validators\Validator

like image 430
Pawan Avatar asked Mar 31 '15 20:03

Pawan


2 Answers

As the 'safe' validator just tells that an attribute may be set by massive assignment, the approach is not appropiate. It just says that when you use the load() method the attribute can get a value. And if not marked as 'safe' it doesn't prevent setting a value with e.g. $model->dhanwantri_bill_number = 'asdf'. So it is not a proper solution.

More precisely: the 'safe' attribute does not have an effect when $model->validate() (which is usually called with $model->save()) gets called. It is only used when $model->load() is called. If you look into the source code of the SafeValidatior class you see that nothing happens with this validator. The validator doesn't do anything. It is just a marker (you may want to compare it to e.g. RequiredValidator). And with load() the 'when' expression is not used. So you can say 'safe' doesn't work with 'when'. The safe validator may get used when the rule gets evaluated but its validateAttribute() is empty so nothing happens in that point in time.

Besides the whenClient in your code doesn't make sense. What should happen here?

I guess there are several ways of realizing that. One idea would be to let the controller set the attributes not by load(), rather set them explicitely and check there if $model->dhanwantri_bill_number should be set or not. Or you could use load() and then revert the attribute after loading according to what $model->bill_type is set.

Or you could implement a setter method for dhanwantri_bill_number in your model and choose there if the attribute gets set or not. Maybe scenario dependent.

like image 66
robsch Avatar answered Nov 02 '22 15:11

robsch


From Yii2 doc:

By default, an active attribute is considered safe and can be massively assigned. If an attribute should NOT be massively assigned (thus considered unsafe), please prefix the attribute with an exclamation character (e.g. '!rank').

Consider to use scenarios to handle your problem. http://www.yiiframework.com/doc-2.0/guide-structure-models.html#scenarios

like image 25
TomaszKane Avatar answered Nov 02 '22 15:11

TomaszKane