Skip to content

MY Validation Callbacks into Models

Derek Jones edited this page Jul 5, 2012 · 25 revisions

Category:Libraries::Validation | Category:Libraries::Community

Setting Up:

        $this->validation->set_rules(array(
            'username'    => 'trim|required|callback_users_model->is_unique[username]',
            'password'    => 'trim|required|matches[confirm]',
        ));

The callback function in users_model

    /**
     * Validation callback
     **/
    function is_unique($value, $field)
    {
        $this->validation->set_message('users_model->is_unique', "The %s {$value} is not available. Try a different username");
        return (bool)(!$this->findBy("{$field} = '{$value}'"));
    }

This is a more advanced version of the previous callbacks into models extension. You must pass the calling object to the Validation class. ie: $this->validation->run($this);

application/libraries/MY_Validation.php

<?php  if (!defined('BASEPATH')) exit('No direct script access allowed');

/**
 * MY_Validation extension
 *
 * Allows callback functions into Module or Models
 * 
 * Version 0.3 (c) Wiredesignz 2008-04-24
 */

class MY_Validation extends CI_Validation 
{
    function get_fields()
    {
        return $this->_fields;
    }
    
    /**
     * Run the Validator
     *
     * This function does all the work.
     *
     * @access    public
     * @return    bool
     */        
    function run(&$parent)
    {        
        // Do we even have any data to process?  Hmm?
        if (count($_POST) == 0 OR count($this->_rules) == 0)
        {
            return FALSE;
        }
    
        // Load the language file containing error messages
        $parent->load->language('validation');
                            
        // Cycle through the rules and test for errors
        foreach ($this->_rules as $field => $rules)
        {
            //Explode out the rules!
            $ex = explode('|', $rules);

            // Is the field required?  If not, if the field is blank  we'll move on to the next test
            if ( ! in_array('required', $ex, TRUE))
            {
                if ( ! isset($_POST[$field]) OR $_POST[$field] == '')
                {
                    continue;
                }
            }
            
            /*
             * Are we dealing with an "isset" rule?
             *
             * Before going further, we'll see if one of the rules
             * is to check whether the item is set (typically this
             * applies only to checkboxes).  If so, we'll
             * test for it here since there's not reason to go
             * further
             */
            if ( ! isset($_POST[$field]))
            {            
                if (in_array('isset', $ex, TRUE) OR in_array('required', $ex))
                {
                    if ( ! isset($this->_error_messages['isset']))
                    {
                        if (FALSE === ($line = $parent->lang->line('isset')))
                        {
                            $line = 'The field was not set';
                        }                            
                    }
                    else
                    {
                        $line = $this->_error_messages['isset'];
                    }
                    
                    // Build the error message
                    $mfield = ( ! isset($this->_fields[$field])) ? $field : $this->_fields[$field];
                    $message = sprintf($line, $mfield);

                    // Set the error variable.  Example: $this->username_error
                    $error = $field.'_error';
                    $this->$error = $this->_error_prefix.$message.$this->_error_suffix;
                    $this->_error_array[] = $message;
                }
                        
                continue;
            }
    
            /*
             * Set the current field
             *
             * The various prepping functions need to know the
             * current field name so they can do this:
             *
             * $_POST[$this->_current_field] == 'bla bla';
             */
            $this->_current_field = $field;

            // Cycle through the rules!
            foreach ($ex As $rule)
            {
                // Is the rule a callback?            
                $callback = FALSE;
                if (substr($rule, 0, 9) == 'callback_')
                {
                    $rule = substr($rule, 9);
                    $callback = TRUE;
                }
                
                // Strip the parameter (if exists) from the rule
                // Rules can contain a parameter: max_length[5]
                $param = FALSE;
                if (preg_match("/(.*?)\[(.*?)\]/", $rule, $match))
                {
                    $rule    = $match[1];
                    $param    = $match[2];
                }

    // Call the function that corresponds to the rule
    if ($callback === TRUE)
    {                    
        /* Allows callbacks into Models */
        
        if (list($class, $method) = split('->', $rule))
        {
            if ( ! method_exists($parent->$class, $method))
            {         
                continue;
            }
        
            $result = $parent->$class->$method($_POST[$field], $param);
        }
        else
        {
            if ( ! method_exists($parent, $rule))
            {         
                continue;
            }
            
            $result = $parent->$rule($_POST[$field], $param);    
        }
        
        /* Original code continues */
        
        // If the field isn't required and we just processed a callback we'll move on...
        if ( ! in_array('required', $ex, TRUE) AND $result !== FALSE)
        {
            continue 2;
        }
    }
    else
                {                
                    if ( ! method_exists($this, $rule))
                    {
                        /*
                         * Run the native PHP function if called for
                         *
                         * If our own wrapper function doesn't exist we see
                         * if a native PHP function does. Users can use
                         * any native PHP function call that has one param.
                         */
                        if (function_exists($rule))
                        {
                            $_POST[$field] = $rule($_POST[$field]);
                            $this->$field = $_POST[$field];
                        }
                                            
                        continue;
                    }
                    
                    $result = $this->$rule($_POST[$field], $param);
                }
                                
                // Did the rule test negatively?  If so, grab the error.
                if ($result === FALSE)
                {
                    if ( ! isset($this->_error_messages[$rule]))
                    {
                        if (FALSE === ($line = $parent->lang->line($rule)))
                        {
                            $line = 'Unable to access an error message corresponding to your field name.';
                        }                        
                    }
                    else
                    {
                        $line = $this->_error_messages[$rule];
                    }                

                    // Build the error message
                    $mfield = ( ! isset($this->_fields[$field])) ? $field : $this->_fields[$field];
                    $mparam = ( ! isset($this->_fields[$param])) ? $param : $this->_fields[$param];
                    $message = sprintf($line, $mfield, $mparam);
                    
                    // Set the error variable.  Example: $this->username_error
                    $error = $field.'_error';
                    $this->$error = $this->_error_prefix.$message.$this->_error_suffix;

                    // Add the error to the error array
                    $this->_error_array[] = $message;                
                    
                    continue 2;
                }                
            }
            
        }
        
        $total_errors = count($this->_error_array);

        /*
         * Recompile the class variables
         *
         * If any prepping functions were called the $_POST data
         * might now be different then the corresponding class
         * variables so we'll set them anew.
         */    
        if ($total_errors > 0)
        {
            $this->_safe_form_data = TRUE;
        }
        
        $this->set_fields();

        // Did we end up with any errors?
        if ($total_errors == 0)
        {
            return TRUE;
        }
        
        // Generate the error string
        foreach ($this->_error_array as $val)
        {
            $this->error_string .= $this->_error_prefix.$val.$this->_error_suffix."\n";
        }

        return FALSE;
    }
}
Clone this wiki locally