I just faced with this "problem" today, CI run my callbacks first and then executes any other rules, you should reconsider respect the original rules order because the pipe/cascading concept is misleading if CI modifies rules order (calling callbacks first), in my case i need to run two custom rules (one rule is defined extending form_validation and the second one is a callback)
lets say:
A: is a rule defined inside form_validation, that does a format check.
B: is callback rule doing a database query.
and the rules order defined in a field are:
$this->form_validation->set_rules('filed','human name',array('trim','required','max_length[38]','min_length[3]','A','callback_B'));
i was expecting A being called before B. but CI calls trim and then B, and later the other rules, so if need to check the format (A) before calling B, and force to use the correct format before tell something in the database, basically i'm forced to do previous checks in B (manually call A) and "bypass" it to allow other rules (A) be called and properly show errors to the users...
this is a weird behavior or at least is not what we can infer from the documentation.
The only issue I see here is that making a fix for this may lead to some BC breaks for developers...
What if we would implement a new method, set_rules_order() ?
i have been thinking in clear way to do this, ins't a little redundant add another method to sort the rules? i have this 3 options/suggestions:
So adding a method for specifying the rules order is redundant, however
- Implement different rule's sorting methods and allow to specify one in the configuration.
is a suggestion you are proposing, being non-redundant. :)
A new Form_validation class... I don't see this happening since it may be a solution you can use for yourself, for your own project, if you really want to use a customized validation class.
Your solutions, just as mine, have in mind adding new functionality/method(s) to the actual Form_validation class. This is what I said as well, however, I didn't propose any technical details. The idea is not to change the _default_ behavior.
Hi gxgpet.
when you said "implement a new method, set_rules_order()", where you meaning to allow implement a custom rule's sorter function? because i originally understood "set_rules_order" like specifically saying the rules order something like this:
$this->form_validation->set_rules('filed','Field','A|B|C|D');
$this->form_validation->set_rules_order('field','D|B|A|C');
that's what i said it was a little redundant, because i found the rules order implicit in the set_rules_order method.
however if you was thinking in something like:
$this->form_validation->set_rules('filed','Field','A|B|C|D');
$this->form_validation->set_rules_order('field','explicit');
that's the same i suggested in the second idea, it was my mistake and i have to apologize. this's maybe a clear way to implement it without modify the default behavior.
have a nice day :+1:
No worries, @moscoquera! I didn't criticize you. I was just pointing out that we should not interfere with the current behavior of form_validation, but add something over it, in order to keep BC breaks-free.
Now based on our discussion, we should wait some official feedback regarding this.
Here's the problem: No matter in what order the rules are executed, there will always be complaints.
While it does make sense for rules to be executed in order of definition, it is also common sense that one rule shouldn't error because of another, and one function call shouldn't change the behavior of another.
That's also true... If there are validation rules which depend on each other, maybe they should be merged together, after all. Or just moved completely separated...
I understand every rule should be independent, BUT i think my callback shouldn't implement a bypass allow other rules to show their errors. by example: showing the error returned by the "A" rule before the B's error, is necessary to avoid OSi's level 8 bugs (make it harder to users screw up). on the other side, allowing certain dependence between the rules (controlled by the developer) is really useful to decrease server load (if you only need to run each validation once). that's my point, it's going to be a lot more clear and easy if we can write callbacks without necessarily need to re-implement those checks.
So ... in short: you understand that rules should be indepentent, but you want them to be dependent. :)
Please provide a concrete use case to demonstrate the problem ... It's really hard to understand if the problem's with 'A' and 'callback_B' without knowing what they do.
Hi narfbg...
what i'm saying is that i understand rules should be independent, BUT it's important be able to write dependent rules like alpha_numeric_spaces should be called after trim.
In my case i had this rules:
function docnumbercheck($str){
if ( ! preg_match("/^\d+$/", $str)){
$this->set_message('docnumbercheck', 'message');
return FALSE;
} else{
return TRUE;
}
}
function isvaliduser($docnum){
if (!$this->docnumbercheck($docnum)){
return true; //bypass
}
$ci=&get_instance();
$ci->load->model('user');
if ($ci->user->searchUserByCodeInRYC($docnum)==null){
$$this->set_message('isvaliduser','message');
return false;
}
return true;
}
what i need to do first is check the input format with docnumbercheck and then check the code i the database using isvaliduser. the codes must be digits only, that's why is important do the format check before check try to check the value in he DB.
isvaliduser was originally implemented as a callback and the rules order is implemented like:
'rules' => 'trim|required|max_length[38]|min_length[3]|docnumbercheck|callback_isvaliduser'
attempting to avoid unnecessary calls to isvaliduser, BUT due that isvaliduser is called before docnumbercheck i had to implement the bypass in isvaliduser to allow docnumbercheck properly show the error to the user.
you declared docnumbercheck in extended library then call it in controller?
maybe you can create a helper for docnumbercheck,and then call docnumbercheck in controller and extended library,
Me:
So ... in short: you understand that rules should be indepentent, but you want them to be dependent. :)
You:
what i'm saying is that i understand rules should be independent, BUT it's important be able to write dependent rules
Come on ... this is comical. You can't agree with a principle and then want to violate it immediately after.
like alpha_numeric_spaces should be called after trim
Incidentally, 'trim' calls trim() - a callable - it does get called before 'alpha_numeric_spaces'. :)
what i need to do first is check the input format with docnumbercheck and then check the code i the database using isvaliduser. the codes must be digits only, that's why is important do the format check before check try to check the value in he DB.
An invalid user "code" wouldn't be found in your database regardless of your other rules - that's not a valid argument at all.
isvaliduser was originally implemented as a callback and the rules order is implemented like:
'rules' => 'trim|required|max_length[38]|min_length[3]|docnumbercheck|callback_isvaliduser'attempting to avoid unnecessary calls to isvaliduser, BUT due that isvaliduser is called before docnumbercheck i had to implement the bypass in isvaliduser to allow docnumbercheck properly show the error to the user.
A lot to say about this ...
So are you saying this is correct. It just odd, surely it should stop and store the first error it comes to from left to right and report that back? Not continuing to check them all.
It does stop; the order of execution is different.
Ok, thanks for getting back to me, so it isn't left to right, it runs the rules possibly in a different order to what has been specified?
As long as I know this I will be caution when using it.
Just like to add, first time I have used your framework, i'm liking it, great work! it would be great if an order option could be added that would really make validation for me even better.
hello again @narfbg.
Come on ... this is comical. You can't agree with a principle and then want to violate it immediately after.
i think there's a huge difference between the ideal way to do the things and the "real" way to do the things. if you have have independent rules the unique benefit you get is that you can isolate bugs more easily, that's partially truth, because as a developers we want to reuse our code, and if we have a bug in a function used in multiple rules it's simply going to propagate; it's actually a lot faster to debug code when you know the exact order it's running (this can be achieved having a clear rule's order).
it's like... i understand vegetarian people but i'm not into it, and i can understand sometimes "vegetarians" actually eats some meat if needed.
- Being able to do performance optimizations isn't a priority, to say the least. Generic form validation isn't an easy problem to solve ... we've barely got it working in a way that satisfies most people.
i know this's not easy, you are doing a great work and i truly appreciate that, i'm just pointing something that can be confusing for some people and it's not mentioned in the docs. just in my point of view, knowing the rules order is more practical if the developers needs to do optimizations. as in my case, where i need to avoid unnecessary calls to a database i can't cache neither.
- If one rule depends on another, then both belong together in a single rule. Nothing is stopping you from combining both rules into a single one, and you do whatever you wish in it. In fact ... you're already doing this; the "bypass" you're doing means that your 'docnumbercheck' rule is redundant.
actually "docnumbercheck" isn't redundant beacuse its being used in other forms. about combining the rules, that's what i'm doing now, but in a better way, I'm replacing all the rules with a "container rule" and calling each one in my custom order, i apologize if at the begging it wasn't clear enough at least for me. (actually, i just figured it out while writing this).
- Message precedence is not realy important. Your users have to resolve all problems with their input data, regardless of which problem they're notified about first.
that's true in a developer POV; but, when you are also the UX designer or your clients are not really tech friendly, you have to make it easier for them, that's why i need to be sure to execute "isvaliduser" at the end, because i can't tell them "you dont exist" when they can only writing the data in a wrong format.
I Apologize if i sound rude or demanding, English isn't obviously my first tongue and i dont know if some words are just aggressive. have a good day.
Dear support, would this issue be fixed in the next CI4 release?
I am new to CI (but experienced developer) and this seems very annoying and not logic at all to me.
Thank you
@bert126 If you have a CI4 support question or feature request, please ask it on the forum. This is the CI3 repository.
Most helpful comment
Here's the problem: No matter in what order the rules are executed, there will always be complaints.
While it does make sense for rules to be executed in order of definition, it is also common sense that one rule shouldn't error because of another, and one function call shouldn't change the behavior of another.