Multi-field validation callbacks, the "login" form problem, etc. |
[eluser]mycroes[/eluser]
[quote author="marmida" date="1195094983"]... This is a possible solution. But it also encourages the use of callbacks to provide dependency and chaining for validations, and this I think is the central topic I'm bringing up - the current validation system does not support anything beyond the scope of a single field at a time, even if arguments are provided that relate to other fields. By using callbacks, it falls outside the scope of CI, which is fine. An example and a counterproposal: Say we have a form with zip and country fields. If the country is US, then the zip must be validated in US zip format. If the country is Canada, then the zip must be validated by Canadian zip code regex. If the country is anything else, we ignore zip entirely (because we're jerks). I've worked with systems with encapsulated rules that would express this in a CI-translated way like: Code: $this->set_rules(array('zip' => 'trim|if[country==ID_USA]{valid_us_zip}else if[country==ID_CANADA]{valid_canada_zip})); This is however a single rule that applies only to a single field and doesn't really touch on the subject of global validations across the entire form. ...[/quote] I understand your point, but I for one really wouldn't want something like that. Of course the idea is nice and it works, but there's two cons: 1. You need to interpret the language used in the rule. Of course you can use php and eval, but that's exactly what you probably don't want to use at all. 2. You need to learn the 'language' that makes up the rules. Whatever the language you choose, that will still be a problem, 'trim|required' is some kind of language too and you need to learn it, but it's relatively simple at ellislab.com/forums/viewthread/64862/ I pointed out a way that seems nice to me to handle the 'one rule for two fields' problem, because I think it's flawed right now, but I think you still should use callback functions instead of writing a new language and writing code in the new language so the validator can parse it... Regards, Michael
[eluser]marmida[/eluser]
[quote author="mycroes" date="1195095710"]1. You need to interpret the language used in the rule. Of course you can use php and eval, but that's exactly what you probably don't want to use at all. 2. You need to learn the 'language' that makes up the rules. Whatever the language you choose, that will still be a problem, 'trim|required' is some kind of language too and you need to learn it, but it's relatively simple at ellislab.com/forums/viewthread/64862/ I pointed out a way that seems nice to me to handle the 'one rule for two fields' problem, because I think it's flawed right now, but I think you still should use callback functions instead of writing a new language and writing code in the new language so the validator can parse it...[/quote] Yeah, it adds a lot of complexity. It doesn't have to be a full-blown language per se; the other system I'm referring to used arrays to contain the rule specifications, so branching for if/else clauses was a lot easier to read and didn't require any real "parsing" to speak of. And yes, this could also be done with a callback.
[eluser]Michael Wales[/eluser]
Code: $rules['name'] = 'trim|required|exact_length[3]|callback__test'; Good example. Have you run this code to see exactly what would happen? It's an interesting experiment that I would like to see the results of (I would test, but knee-deep in a client contract atm).
[eluser]Michael Wales[/eluser]
Ignore this: I just tested and my password field is in fact, not trimming the spaces - therefore the rules of the password field are not applied prior to calling the callback method. I think these are pretty unique circumstances that all have a workaround (in this case). Nonetheless, if someone can find a graceful and easy to use solution - I'm sure it would be a welcome addition to the codebase. You know, now that I think about it - I think it will still work as I imagine. I do virtually the same thing with all of my login forms. Once again, without testing, but just using logic the following two strings would produce different hashes: "password" " password " Yet, when I try to login, both of these strings may be entered into the login form for a successful login (this is by design - the password field has a trim). So, obviously the rules of the password field are being set in-place prior to calling the callback function. Otherwise, we would have an invalid login for the second string (as the pre and appended spaces would generate a hash that differs from the hash stored in the database).
[eluser]marmida[/eluser]
[quote author="mycroes" date="1195094402"]So what will this output? There's no documentation that says in what order the checks will execute, so we can have 2 cases: 1. first name is checked, during the check the _test function is called and the password isn't converted to md5 yet and the _test function will just print the text (password) entered by the user 2. password is checked first, after that name is checked and the _test function will output the md5 encrypted password.[/quote] From the Validation class line 191: Code: // Cycle through the rules and test for errors It relies on foreach, which iterates in the order that the items were added to the array (or their order in the array() language construct). So in your case you will always fire the rules for whichever field is first in the arg passed to set_rules().
[eluser]marmida[/eluser]
[quote author="walesmd" date="1195109795"]I think these are pretty unique circumstances that all have a workaround (in this case). Nonetheless, if someone can find a graceful and easy to use solution - I'm sure it would be a welcome addition to the codebase.[/quote] This is neither as graceful nor as easy to use as I'd like, but here's the patch I hacked in: http://marmida.com/ci/ci_validation_glob...back.patch I loaded this by putting my modified Validation.php into the app's libraries/ dir, you don't have to actually overwrite the original one. From the controller's point of view: Code: $this->validation->set_fields(array( It'd be a lot nicer if this was had the interface of regular rules (e.g. $this->set_global_rules('rule_a|rule_b|callback__rule_c')) but there are some considerations with field name replacements to consider in the error messages that I don't have time to consider right now. Callbacks avoided this, since the callback is then responsible for setting the error message manually. |
Welcome Guest, Not a member yet? Register Sign In |