Skip to content

MY Validation Callbacks into Models

World Wide Web Server edited this page Jul 4, 2012 · 25 revisions

Category:Validation Category:Libraries Category:Libraries::Validation Category:Libraries::Core Extensions

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

[/code]

The callback function in users_model [code] /** * 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}'")); }

[/code]

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 [code] <?php if (!defined('BASEPATH')) exit('No direct script access allowed');

/**

  • MY_Validation extension
  • Allows callback functions into Module or Models
  • Usage:
  • Pass the caller to the validation class
  • $this->validation->run($this);
  • Version 0.2 (c) Wiredesignz 2008-04-18 */

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->lang->load('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;
}

} [/code] To integrate a "unique" validation into models based on the Activerecord_Class_Mod library, simply tie in the object features and put your standard callback functions into application/libraries/Activerecord.php: [code]
function is_unique($value, $field) { $this->validation->set_message($this->_class_name.'->is_unique','The %s "'.$value.'" is not available. Try a different %s.'); $this->db->where($field,$value); $this->db->from($this->_table); return ($this->db->count_all_results() == 0); } [/code]

Clone this wiki locally