Yii 1.1: yii-conditional-validator

If-then validation rules using core validators!
36 followers

Note: This version (1.0.0) is not compatible with earlier versions.

General Information

YiiConditionalValidator (YCV) validates some attributes depending on certains conditions (rules). You can use any core validator as you usually would do or any other class based or inline validator. An interesting feature is that you can use dot.notation in your rules to achieve data in related models and you can even use the own YiiConditionalValidator inside itself to perform more complex conditions;

Basically, YCV executes the rules set in the param if and if there are no errors executes the rules set in the param then.

Info: Please, visit the project's website and don't hesitate to fork it on github!

Syntax

array('safeAttribsList', 'path.to.YiiConditionalValidator',
    'if' => array(
        //rule1: array('attrX, attrY', 'required', ...)
        //ruleN: ...
    )
    'then' => array(
        //rule1: array('attrZ, attrG', 'required', ...)
        //ruleN: ...
    )
)
  • safeAttribsList: The name of the attributes that should be turned safe (since Yii has no way to make dinamic validators to turn attributes safe);
  • path.to.YiiConditionalValidator: In the most of cases will be ext.YiiConditionalValidator;
  • if: (bidimensional array) The conditional rules to be validated. Only if they are all valid (i.e., have no errors) then the rules in then will be validated;
  • then: (bidimensional array) The rules that will be validated only if there are no errors in rules of if param;

Note: Errors in the rules set in the param if are discarded after checking. Only errors in the rules set in param then are really kept.

Examples

If customer_type is "active" then birthdate and city are required:

public function rules()
{
    return array(
        array('customer_type', 'ext.YiiConditionalValidator',
            'if' => array(
                array('customer_type', 'compare', 'compareValue'=>"active"),
            ),
            'then' => array(
                array('birthdate, city', 'required'),
            ),
        ),
    );
}

If customer_type is "inactive" then birthdate and city are required and city must be "sao_paulo", "sumare" or "jacarezinho":

public function rules()
{
    return array(
        array('customer_type', 'ext.YiiConditionalValidator',
            'if' => array(
                array('customer_type', 'compare', 'compareValue'=>"active"),
            ),
            'then' => array(
                array('birthdate, city', 'required'),
                array('city', 'in', 'range' => array("sao_paulo", "sumare", "jacarezinho")),
            ),
        ),
    );
}

If information starts with 'http://' and has at least 24 chars length then the own information must be a valid url:

public function rules()
{
    return array(
        array('information', 'ext.YiiConditionalValidator',
            'if' => array(
                array('information', 'match', 'pattern'=>'/^http:\/\//'),
                array('information', 'length', 'min'=>24, 'allowEmpty'=>false),
            ),
            'then' => array(
                array('information', 'url'),
            ),
        ),
    );
}

Validation using related data

Note: This feature may not fit into situations too much complex.

You can use dot.notation in attribute name to fetch data from a related model in your rules.

Example:

Assuming that Customer has a relation 'profile', you could check (in customer rules) if the profile.username is not empty before validate something:

//Customer Model
public function rules()
{
    return array(
        array('information', 'ext.YiiConditionalValidator',
            'if' => array(
                //would only return true if profile.username is not empty
                array('profile.username', 'required'),
            ),
            'then' => array(
                array('someAttrib', 'someValidation', ...),
            ),
        ),
    );
}

Installation

  1. Put YiiConditionalValidator.php in your application.extensions folder;

Requirements, Help and Reference

Changelog and ToDo

  • [Version 1.0.0]

    • Usage made yet more easier, simplyfied and objective;
    • New if/then operators replace validations/dependentValidations making the use more natural;
    • Code completely refactored and (almost) commented;
    • Allows to use multiple attributes and/or validator combinations in the same set of YCV rule;
  • [Version 0.2.0]

    • Usage made easier, more simplyfied and more objective;
    • New 'dot.notation' usage on attributes name (will be improoved on next versions);
    • Some bug fixes;
  • [ToDo]

Total 12 comments

#16577 report it
KonApaz at 2014/03/07 05:25am
order of rules

If I add the rule as the first one everything is ok If I add the rule as the last one then applied only this, bypassing over the others, except if this sufficer and then the orher rules applied properly

Am I missing something ?

#15501 report it
Nabi at 2013/11/15 04:27pm
use Scenario of rule maybe better

I thinks can be used Scenario of rule (+ , +) easily, instead use this extension and If/Then.

#15085 report it
makmende at 2013/10/06 04:21am
error while validating multi-model form

Thanks sidtj for the great extension...It seems exactly what am looking for. I can however not seem to have it work when using it in a form capturing related data.

Here are my rules

array('user_id', 'numerical', 'integerOnly'=>true), array('event_id, campaign_id', 'length', 'max'=>7), array('q1, q2, q3, q4, q5, q6, q7, q8, q9, q10', 'length', 'max'=>100),
array('q1', 'ext.YiiConditionalValidator', 'if' => array( array('event.code_id', 'compare', 'compareValue'=>"303"), ), 'then' => array( array('q1', 'required'), ), ),...

and here are the relations

public function relations() { // NOTE: you may need to adjust the relation name and the related // class name for the relations automatically generated below. 
return array( 'user' => array(self::BELONGS_TO, 'Users', 'user_id'), 'event' => array(self::BELONGS_TO, 'EventsAll', 'event_id'), ); }

When I try to save I get the following error though...

AdhocVoc has not a relation named "event". Check the YiiConditionalValidator rule that is using the attribute name "event.code_id".

Where am i going wrong?

#10913 report it
Neil Bardos at 2012/12/02 07:57pm
Fixed!

Hi Sidtj,

i disabled the client side validation and it works! Thanks!

'enableClientValidation' => false,
#10876 report it
sidtj at 2012/11/29 05:12am
RE: Same Problem as seniorboss

Hi Neil Bardos,

YCV may not work for client-side validation for now. Try to use server-side validation.

Hope it works.

#10867 report it
Neil Bardos at 2012/11/28 08:33pm
Same Problem as seniorboss

Downloaded the extension and tried implementing it using this code. Did I missed something? I am new to Yii and any help would be greatly appreciated.

public function rules() {
        return array(
            array('physicianInitials, physicianLastname, diabetesMilletus, cortisonUsed, smoking, handDominancy', 'required', 'on' => 'followUp1'),
            ##for conditional validation
            //if cortisonUsed is Yes, dosage is required (Yes has a value of 1)
            array('cortisonUsed', 'application.extensions.YiiConditionalValidator',
                'if' => array(
                    array('cortisonUsed', 'compare', 'compareValue' => 1),
                ),
                'then' => array(
                    array('cortisonDosage', 'required'),
                ),
            ),
        );
    }

Note: cortisonDosage text field is required once cortisonUsed value is 1 [Yes].

The native Form Validation works but it doesnt displays error messages when cortisonDosage is empty.

Thanks in advance guys!

#10182 report it
vinu at 2012/10/09 06:48am
Client side dependant validations

I also need the help for client side validations for elements which are enabled on any event of another elements.....

#9773 report it
seniorboss at 2012/09/09 06:43pm
Very Good Work

Very good work, and thank you to developer for precious support!!

#9744 report it
seniorboss at 2012/09/07 07:12pm
same thing

i tried with other field but is the same thing, nothing work. No error message in log either in browser console. What can i send you to help me to solve the problem?

following my validation rule

return array(
            array('venditore, stato, vendi_a, titolo, descrizione, lingua_default', 'required'),
            array('venditore, attivo, quantita, articolo_permanente, accetta_condizioni', 'numerical', 'integerOnly'=>true),
            array('stato, codice_magazzino, offerta_privati, offerta_azienda', 'length', 'max'=>45),
            array('vendi_a', 'length', 'max'=>20),
            array('video, immagine', 'length', 'max'=>255),
            array('peso, altezza, lunghezza, larghezza, lingua_default, prezzo_privati, prezzo_azienda, percentuale_sconto_privati, soglia_trasporto_gratuito_privati, percentuale_sconto_azienda, soglia_trasporto_gratuito_azienda, minimo_ordine', 'length', 'max'=>10),
            array('titolo, titleTag', 'length', 'max'=>65),
            array('descrizione, h1Tag', 'length', 'max'=>250),
            array('descriptionTag, keywordTag', 'length', 'max'=>160),
                        //array('immagine', 'file','types'=>'jpg, gif, png','allowEmpty'=>true, 'on'=>'update'),
                        array('video', 'file','types'=>'avi, mpeg, mpg, flv, mov, wmv', 'allowEmpty'=>true, 'on'=>'update'),                        
                        array('titolo','unique'),
            array('cat','safe'),
            array('dataInserimento, dataScadenza, ultimoRinnovo, scadenzaB2B, ultimoRinnovoB2B, inizio_offerta_privati, termine_offerta_privati, inizio_offerta_azienda, termine_offerta_azienda', 'safe'),
 
                        array('vendi_a', 'application.extensions.YiiConditionalValidator',
                                'validation'=>array('compare', 'compareValue'=>'privati'),
                                'dependentValidations'=>array(
                                    'prezzo_privati'=>array(
                                        array('required')
                                    ),
                                ),
                        ),
 
                    // The following rule is used by search().
            // Please remove those attributes that should not be searched.
            array('id, venditore, dataInserimento, dataScadenza, ultimoRinnovo, attivo, stato, vendi_a, scadenzaB2B, ultimoRinnovoB2B, video, immagine, quantita, codice_magazzino, articolo_permanente, peso, altezza, lunghezza, larghezza, offerta_privati, offerta_azienda, titolo, descrizione, titleTag, descriptionTag, h1Tag, keywordTag, lingua_default, accetta_condizioni, prezzo_privati, prezzo_azienda, percentuale_sconto_privati, soglia_trasporto_gratuito_privati, inizio_offerta_privati, termine_offerta_privati, percentuale_sconto_azienda, soglia_trasporto_gratuito_azienda, inizio_offerta_azienda, termine_offerta_azienda, minimo_ordine', 'safe', 'on'=>'search'),
 
 
        );
#9742 report it
sidtj at 2012/09/07 05:51pm
RE: #9741

Try to make different validations using another fields and rules for testing. Let me know the problems you may have. Everything is working in all of projects I use YCV in.

#9741 report it
seniorboss at 2012/09/07 05:27pm
doesn't work

I followed all the steps, but nothing is working. I try with a simple test.

array('vendi_a', 'application.extensions.YiiConditionalValidator',
                                'validation'=>array('compare', 'compareValue'=>'privati'),
                                'dependentValidations'=>array(
                                    'prezzo_privati'=>array(
                                        array('required')
                                    ),
                                ),
                        ),

if 'vendi_a' is equal to 'privati' then 'prezzo_privati' must be insert. When prezzo_privati is empty no error message appears. I use the last version of yii, is this the problem?

#9540 report it
emte at 2012/08/22 03:19am
client side validation

Hi, is it possible to create client side conditional validation like you described for backend?

Leave a comment

Please to leave your comment.

Create extension