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]

application/libraries/MY_Validation.php [code] <?php if (!defined('BASEPATH')) exit('No direct script access allowed');

/**

  • MY_Validation Extension

  • Allows callback functions into Models or Modules

  • Version 0.1 (c) Wiredesignz 2007-12-25 / class MY_Validation extends CI_Validation { / return the validation fields array */ function get_fields() { return $this->_fields; }

    /**

    • Run the Validator

    • This function does all the work.

    • @access public

    • @return bool */
      function run() { // 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 $this->CI->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 = $this->CI->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) {
    /* Added callbacks into Models or Modules */

     if (list($class, $method) = split('->', $rule))
     {
         if (!method_exists($this->CI->$class, $method))
         {         
             continue;
         }
         
         $result = $this->CI->$class->$method($_POST[$field], $param);
     }
     else
     {
         if (!method_exists($this->CI, $rule))
         {         
             continue;    
         }
         
         $result = $this->CI->$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 = $this->CI->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