How to use callbacks in validation the correct way? |
[eluser]Warz[/eluser]
Hi, So I got two controllers: - Register - Profile I already created a few nice functions in Register. For instance, this one: Code: function valid_date() What is the best way to do this?
[eluser]Jelmer[/eluser]
I must admit it isn't the pretiest solution, but I solved it like this (PHP5 only): - I place custom validation rules in the model instead of in the controller - they're all prefixed with a single underscore - I add the following "magic method" from PHP5 which is called when an undefined method is called. Also it works solely on methods prefixed with an underscore and calls them from the model (it also asumes the model is already loaded): Code: function __call($function, $args) Code: $this->form_validation->set_rules('pass', 'Password', 'trim|callback__secure_password');
[eluser]Warz[/eluser]
Thanks for you solution, so you do like this?: Controller: register.php Code: function Register() { Code: function _valid_date() I tried this, and it would not call _valid_date() I don't understand how set_rules will know that the callback function is placed in the model? How to say: callback__(User_model)__valid_date... ?
[eluser]Jelmer[/eluser]
The __call() function should be in the controller. The Form_validation class requests the callback rule in the controller, so the magic method should catch the function for not-existing in the controller. If you only need rules from 1 model you can solve it like this - to be put in the controller: Code: function __call($function, $args) If you might need to use this with multiple models you might do it like this: - make sure all models are 1 word and postfixed with "_model" - put the model name as the first part of the function and seperate it from the second part using an underscore - change the __call() function to something like this (untested code): Code: function __call($function, $args) Code: $this->form_validation->set_rules('year','Date','required|callback__user_valid_date');
[eluser]Warz[/eluser]
Thanks again, I couldn't get it to call "__call" function for some reason, I will look more into it tomorrow. However I'm wondering how come you didn't use a Controller class to put these validations in and then extend it? Isn't that possible too?
[eluser]Jelmer[/eluser]
Like putting the rules in an extended MY_Controller you mean? Mostly because I don't need those validation rules everywhere and I might need combinations of multiple sets of rules so different base controllers doesn't really work either. It will work, and it will work quite well in smaller applications. But in larger applications where you're working with multiple models that might need their validation functions shared, this will become quite ugly. Also: if __call() doesn't work that might be because you're not using PHP5.
[eluser]Warz[/eluser]
Like making a controller called "User" then extend like this: Register extends User Profile extends User And in the "User" controller you keep all validation functions and then in Profile for instance you may then call whatever you need by set_rules and callback (By the way I tried this too and couldn't get it working). I am running the script in wamp server with php 5.3.0 so there must be something else causing it, weird thing.
[eluser]Unknown[/eluser]
[quote author="Warz" date="1273889834"]Like making a controller called "User" then extend like this: Register extends User Profile extends User And in the "User" controller you keep all validation functions and then in Profile for instance you may then call whatever you need by set_rules and callback (By the way I tried this too and couldn't get it working). I am running the script in wamp server with php 5.3.0 so there must be something else causing it, weird thing.[/quote] I was having this issue to and found out that the problem is in the form_validation library. Around line 583 in /system/libraries/form_validation.php you will find: Code: if ( ! method_exists($this->CI, $rule)) CI is checking if the callback method exists which it doesn't so it skips calling the function all together. After I commented out this line the __call() method works perfectly. Hope that helps.
[eluser]MT206[/eluser]
What about extending the form_validation library? Wouldn't that work? Then the valid date function could be used like any other validation type.
[eluser]Jelmer[/eluser]
That would work fine for rules that may be usefull in general. This solution is meant for rules that are specific to certain models in larger applications. You could still keep extending the Form_validation class but in the end that will make the class impossible to keep track of, and if you ever need those rules but not need form validation you will need to load the whole class (which is quite illogical). Whichever solution is the best depends on the size of your application and on how much effort you're willing to put in to keep your application logical (specific validation rules belong with the model in my opinion). Keeping things logical will take a little more time in the beginning, but will pay off handsomely in the end when you're extending your application or changing things around after not having seen the code for a while. But you're right, I should have mentioned it in the beginning - it's an easier solution, though only a better one when the rules are non-specific. I sometimes forget the simple solutions after I've found solutions I consider to be better. You could also solve this by allowing a way to load a model's methods from within the form_validation class - in the end I prefered the __call() solution because otherwise you'll have to copy-paste the entire validation loading function in the form_validation extention just to add a few lines in the middle (and I always prefer to use the original class methods as much as possible). |
Welcome Guest, Not a member yet? Register Sign In |