CodeIgniter Forums

Full Version: Form validation MIN or MAX on posted array fields
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi,

While working on my project I found that CI does not have any rules for posted field arrays for checking if the array contains a minimum or maximum allowed selection. When using min_length or max_length CI validates each value within the array, but not the array count itself.

Sometimes your form will have a multi select or check boxes. And you would like too set a minimum or maximum on that field. (Please select at least 2 values OR No more than 3 selections allowed)

I added two rules by extending the Form_validation class and extended the _execute method.

The added methods:

min_selection
PHP Code:
/**
 * Minimum selection on checkboxes or multi select
 *
 * @access    public
 * @param    string
 * @param    value
 * @return    bool
 */
public function min_selection($array$val) {
    if( ! 
is_array($array) ) {
        return 
FALSE;
    }

    
// Lets check for empty array elements and remove them
    
foreach($array as $key => $value) {
        if( 
mb_strlen($value) <= ) {
            unset(
$array[$key]);
        }
    }
        
    return ( 
$val <= count($array) );


max_selection
PHP Code:
/**
 * Max selection on checkboxes or multi select
 *
 * @access    public
 * @param    string
 * @param    value
 * @return    bool
 */
public function max_selection($array$val) {
    if( ! 
is_array($array) ) {
        return 
FALSE;
    }

    
// Lets check for empty array elements and remove them
    
foreach($array as $key => $value) {
        if( 
mb_strlen($value) <= ) {
            unset(
$array[$key]);
        }
    }
    
    return ( 
$val >= count($array) );


The extended method _execute

PHP Code:
/**
 * Executes the Validation routines
 *
 * @param    array
 * @param    array
 * @param    mixed
 * @param    int
 * @return    mixed
 */
protected function _execute($row$rules$postdata NULL$cycles 0) {
        
    
// Lets check if a min or max selction rule has been set
    
$validate_min_max FALSE;
    
    foreach (
$rules as $key => $rule) {
        if( 
strpos($rule'min_selection') !== FALSE OR strpos($rule'max_selection') !== FALSE ) {
            
$validate_min_max TRUE;
            unset(
$rules[$key]);
            break;
        }
    }
        
    
// Found a min or max selection rule
    
if( $validate_min_max ) {
            
        
// Set the method rule and param
        
$param FALSE;
        if ( 
preg_match('/(.*?)\[(.*)\]/'$rule$match) ) {
            
$rule $match[1];
            
$param $match[2];
        }
        
// When empty of not an array, convert
        
if( empty($postdata) OR ! is_array($postdata) ) {
            
$postdata = array($postdata);
        }
            
        
// Run the rule
        
$result $this->$rule($postdata$param);
        
        
// Did the rule test negatively? If so, grab the error.
        
if( ! $result ) {
            
$line $this->_get_error_message($rule$row['field']);
            
            
// Build the error message
            
$message $this->_build_error_msg($line$this->_translate_fieldname($row['label']), $param);
                    
            
// Save the error message
            
$this->_field_data[$row['field']]['error'] = $message;
                
            if ( ! isset(
$this->_error_array[$row['field']]))
            {
                
$this->_error_array[$row['field']] = $message;
            }
        }
    }
    
    
// Validate the rest of the rules as normal
    
parent::_execute($row$rules$postdata$cycles);


The extended _execute method will first check if min_selection or max_selection has been set as a rule. If they have been set, the methods are executed for validation. When found, the rule is removed from the rules array so that the remaining rules can be validated as normal.

Add these lines to the form_validation_lang.php as default error messages
Code:
$lang['form_validation_min_selection']        = 'The {field} field must contain at least {param} selections.';
$lang['form_validation_max_selection']        = 'The {field} field cannot contain more than {param} selections.';

That should be it. Your CI can now validate posted field arrays based on minimum or maximum selection rules

Should you find any bug or problem with the code, please let me know.

– Kind regards,
Martin
Forgot this.

To use the rules just add it like this

PHP Code:
$this->form_validation->set_rules('checkboxes''Some checkboxes''required|min_selection[2]|max_selection[5]'); 
Has anybody had any use for this?
It is rather a specialist condition. I have never had a need for anything other than at least one of the options must be chosen, and that is easily achieved. However you method for achieving your goal was quite an interesting one. I am guessing most people would use a callback and write their own function that way.

Best wishes,

Paul.
Thanks for the feedback.

We build quite a lot of forms for our customers that require this option. Reservation and survey forms need it al the time. So I came up with this and just wanted to share it.

Best wishes,

Martin
Thanks for sharing - it is appreciated :-)
I am use callbacks in this case, but your way is most simple. I'll use your code to refact my project.

PHP Code:
$this->form_validation->set_rules('checkboxes[]''checks''required|callback_valid')->set_message('valid''Max 2 options');

public function 
valid()
 
   {
 
       $num count($this->input->post('checkboxes'));
 
       if ($num 2) {
 
           return false;
 
       } else {
 
           return true;
 
       }
 
   
(04-15-2017, 11:24 AM)joao.coelho Wrote: [ -> ]I am use callbacks in this case, but your way is most simple. I'll use your code to refact my project.

How is the code working out for your project?