CodeIgniter Forums
Custom validation callbacks trouble - Printable Version

+- CodeIgniter Forums (https://forum.codeigniter.com)
+-- Forum: Archived Discussions (https://forum.codeigniter.com/forumdisplay.php?fid=20)
+--- Forum: Archived Development & Programming (https://forum.codeigniter.com/forumdisplay.php?fid=23)
+--- Thread: Custom validation callbacks trouble (/showthread.php?tid=32204)



Custom validation callbacks trouble - El Forum - 07-15-2010

[eluser]Heyimjohn[/eluser]
First off, let me just say that I LOVE CodeIgniter and will be using it for every site I ever have to develop!

Now, on to the trouble I am having. I am trying to use custom callbacks to see if, for example, an email is already in use by another user or if a phone number matches a regular expression. Let me show you what I have in place right now:

Here I set the validation rules
Code:
$this->form_validation->set_rules('email', 'Email', 'required|trim|valid_email|max_length[128]|callback_check_email|xss_clean');

and here is the callback function
Code:
function check_email($str) {
        $query = $this->db->get_where('users', array('email' => $str));
        
        if($query->num_rows() > 0) {
            $this->form_validation->set_message('check_email', 'This email is already in use.');
            return false;
        } else {
            return true;
        }
    }

Its like CI is just ignoring the callback. This occurs for both the function above, and when I check the user's phone number against a regular expression. What am I doing wrong here?

Thanks!


Custom validation callbacks trouble - El Forum - 07-16-2010

[eluser]flaky[/eluser]
Are you using HMVC by any chance?


Custom validation callbacks trouble - El Forum - 07-16-2010

[eluser]Heyimjohn[/eluser]
I'm not really sure what the H means in HMVC, so I guess not?

Edit: is it because I am making them in a model class?


Custom validation callbacks trouble - El Forum - 07-16-2010

[eluser]Luis Perez[/eluser]
Probably, you should write validations in the controller, not in the model. The callbacks only works with controllers.


Custom validation callbacks trouble - El Forum - 07-16-2010

[eluser]Heyimjohn[/eluser]
Well that explains that. So I have to do ALL my validation stuff in the controller and not in the model? Or can I just write the callbacks in the controller?


Custom validation callbacks trouble - El Forum - 07-16-2010

[eluser]flaky[/eluser]
yep, write the callbacks in the controller


Custom validation callbacks trouble - El Forum - 07-16-2010

[eluser]Luis Perez[/eluser]
yes, you need to do all your validations in the controller when you are using callbacks. If you have some validations on your model (with the form_validation functions) there's no problem. You can extend the form_validation class too instead to use controllers callbacks Smile


Custom validation callbacks trouble - El Forum - 07-16-2010

[eluser]WanWizard[/eluser]
Well, it's a big vague.

The form_validation library checks for the existence of the method by
Code:
$this->CI =& get_instance();
if ( ! method_exists($this->CI, $rule))
{
    continue;
}

So it looks for callback methods using the CI superobject pointer.

A big of debugging shows that it points to the controller loaded by the 'front controller'. If you are, like me, in a modular environment where one controller can call other controllers, chances are that callbacks are never going to work, since $this->CI points to the parent controller, not you your module controller. You can test that by adding a "var_dump($this->CI);" in front of the code above, and see which object is dumped. In my case, it's the controller that is loaded after routing. Either way, callbacks in anything other than that controller are not possible.

It would be logical to look for callbacks in the class that called form_validation->run(), but it looks like it doesn't work like that. To be able to do this, you would need to pass $this as a parameter of the run() method, so that the calling method can be accessed.


Custom validation callbacks trouble - El Forum - 07-16-2010

[eluser]WanWizard[/eluser]
Extend the form_validation library:
Code:
class MY_Form_validation extends CI_Form_validation
{
    // storage for the callback object
    var $callback = FALSE;

    // -----------------------------------------------------------------

    /**
     * Constructor
     *
     * @return void
     * @access public
     */
    function MY_Form_validation()
    {
        // call the parent constructor
        parent::CI_Form_validation();

        // set the default callback object
        $this->callback = $this->CI;

        // Logs initialization message for debugging
        log_message('debug', 'ExiteCMS Form Validation Class Extension Initialized');
    }
}

Then copy the _execute() method from the CI library to your library, find the bit where the callback method is checked, and replace it by:
Code:
// Call the function that corresponds to the rule
if ($callback === TRUE)
{
    if ( ! method_exists($this->callback, $rule))
    {
        continue;
    }
    // Run the function and grab the result
    $result = $this->callback->$rule($postdata, $param);

After this, you can set the object that contains your callback functions using
Code:
$this->form_validation->callback =& $this; // callback methods can be found in this class
before calling the run() method to have your fields validated.