EllisLab text mark
Advanced Search
1 of 2
1
   
Validation of listbox, checkbox groups and reselect multiple values using set_select, set_checkbox / Sol: Array to string conversion error (line 709)
Posted: 01 March 2008 02:52 AM
Avatar
Joined: 2008-02-27
14 posts

Overview:
CI is not dealing with user submitted array values properly.

Impacts:
* You cannot validate listbox (select with multiple enabled), checkbox groups and reselect the user selected values using set_select, set_checkbox for multiple values

* You cannot use trim, htmlspecialchars or any other native php function in rules

* When you enable XSS_Clean in config.php error will pop-up when user select multiple values in list box or check checkbox groups ( ie: checking multiple checkboxes for hobbies in html form )

* You cannot use any other validation rules that CI provides like numeric, integer, xss_clean


What this post address:
This post address the following:

* Allowing to use trim, required, htmlspecialchars or any other native php function call in the rules.

* Allowing to use set_select, set_checkbox for listboxes and checkbox groups, checkboxgroupname_error, listboxname_error

Note:
Still you cannot use CI’s validation rules like integer, numeric, xss_clean for arrays. But I don’t think these validation will be needed for listboxes and checkbox groups as you are not going to store these values in db / re-display in html. Mostly, you will make use of the values from db / array to populate, validate against user submitted values.

But if you still need to validate for any purpose, you can call those functions in a loop for all the user selected values in a listbox / checkbox.


Solution:
Enabling CI’s - Validation library to support list box and check box group is involve replacing the system’s Validation.php with our version. To enable this copy system/library/validation.php to application/library/ and do the necessary modification listed below.

This file contains the following modifications:

1. set_select method has been modified to support arrays: (line 617 in original validation.php )

function set_select($field ''$value '')
    
{
        
if ($field == '' OR $value == '' OR  ! isset($_POST[$field]))
        
{
            
return '';
        
}
        
        
if(is_array($_POST[$field])) {
            
if(in_array($value,$_POST[$field])) {
                
return ' selected="selected"';
            
}
        } 
elseif ($_POST[$field] == $value{
            
return ' selected="selected"';
        
}
        
    } 

2. set_checkbox has been modified to support arrays: (line 669 in original validation.php )

function set_checkbox($field ''$value '')
    
{
        
if ($field == '' OR $value == '' OR  ! isset($_POST[$field]))
        
{
            
return '';
        
}
        
        
if(is_array($_POST[$field])) {
            
if(in_array($value,$_POST[$field])) {
                
return ' checked="checked"';
            
}
        } 
elseif ($_POST[$field] == $value{
            
return ' checked="checked"';
        
}
    } 


3. Prep_for_form function has been updated: (line 694 in original validation.php )

function prep_for_form($data '')
    
{
        
if (is_array($data))
        
{
            
foreach ($data as $key => $val)
            
{
                $data[$key] 
$this->prep_for_form($val);
            
}
        }
        
        
if ($this->_safe_form_data == FALSE OR $data == '')
        
{
            
return $data;
        
}
        
        
if(is_array($data)) {
            
return $data;
        
else {
            
return str_replace(array("'"'"''<''>'), array("&#39;""&quot;"'<''>'), stripslashes($data));    
        
}
    } 

4. Method php_func_caller has been added. This enables setting rules like trim, htmlspecial chars and other native php function calls that take single parameter and return the same.

/**
     * native php function caller
     *
     * This function calls native php functions for each values submitted from the form
     *
     * @access    public
     * @param    string
     * @return    string
     * @author r.vadivelan / hivelan [.at.] gmail [.dot.] com
     */
    
function php_func_caller($rule$data '')
    
{
        
if (is_array($data))
        
{
            
foreach ($data as $key => $val)
            
{
                $data[$key] 
$this->php_func_caller($rule,$val);
            
}
        }
        
        
if ($data == '')
        
{
            
return $data;
        
}
        
        
if(is_array($data)) {
            
return $data;
        
else {
            
return $rule($data);
        
}
    } 

5. Call the php_func_caller when processing rules ( Line no 302 in original validation.php )

if (function_exists($rule))
                        
{
                            $_POST[$field] 
$this->php_func_caller($rule,$_POST[$field]);
                            
$this->$field $_POST[$field];
                        


How to test

* Create a html file containing a select box with multiple enabled, and a checkbox group like hobbies. Make use of set_select, set_checkbox, error_string, checkboxgroupname_error, listboxname_error so that we can verify everything work properly.

* Create a controller, initialize validation libarary, set the rules and fields. Make sure you set trim, required and any other native php functions as rules. Rules like xss_clean, interger ( those given by CI ) will not work ( as CI’s validation function’s don’t support arrays).

Now it would be possible to validate listbox and checkboxes without any problem.

Summary:
Even though I have explained in detail, the entire process is very simple:
1. Just copy system/library/Validation.php to application/library and do the modifications.

2. Validate the listbox and checkbox group as you will normally do for other fields.

Hope this will be useful to you. Please let me know your comments.

 Signature 

Validation: Enable CI to validate forms with multiple select (listboxes), checkbox groups, re-select listbox and multiple checkboxes

 
Posted: 02 March 2008 01:46 PM   [ # 1 ]   [ Rating: 0 ]
Avatar
Joined: 2006-04-20
712 posts

Very nice addition !
I have bookmarked it and will test it in a next project.

 Signature 

Un blog seo white-hat expliquant quelques techniques intéressantes sur le seo black hat

Ionize CMS - Webdesigner CMS based on CodeIgniter
http://www.ionizecms.com

My website: Webagency Too Pixel

 
Posted: 03 March 2008 05:53 AM   [ # 2 ]   [ Rating: 0 ]
Avatar
Joined: 2008-02-27
14 posts

Welcome. Email me if you need the modified validation.php file.

 Signature 

Validation: Enable CI to validate forms with multiple select (listboxes), checkbox groups, re-select listbox and multiple checkboxes

 
Posted: 03 March 2008 06:08 AM   [ # 3 ]   [ Rating: 0 ]
Joined: 2006-07-14
4237 posts

I’ve responded in another thread to set the form elements in the form helper instead of the validation library.

But i don’t understand the use of the php_func_caller method. The validation library does process native php functions added as rules. Check the Validation user guide page under the title Prepping Data.

 
Posted: 03 March 2008 08:20 AM   [ # 4 ]   [ Rating: 0 ]
Avatar
Joined: 2008-02-27
14 posts

CI will not call native function calls for array values submitted by end user. For eg: select multiple, check box groups selected by users, CI will try to call the native php function with array and that will result in error / will not work. This function takes every element and will run the php function for it.

Please have a look at the attached image in the end of the post. That show you the user can select multiple values and this code will still apply all the trim, htmlspecialchars etc

 Signature 

Validation: Enable CI to validate forms with multiple select (listboxes), checkbox groups, re-select listbox and multiple checkboxes

 
Posted: 12 May 2008 12:56 PM   [ # 5 ]   [ Rating: 0 ]
Avatar
Joined: 2002-06-03
6547 posts

I can agree to part of this being a bug, but some of it is feature request, albeit the line is a bit blurry.  Would you mind zipping and attaching the controller and view files you are using to this thread?

 Signature 
 
Posted: 16 May 2008 03:27 PM   [ # 6 ]   [ Rating: 0 ]
Avatar
Joined: 2008-02-27
14 posts

Hi Derek
Apologize. Just seen your last post. Sending the file right away.

 Signature 

Validation: Enable CI to validate forms with multiple select (listboxes), checkbox groups, re-select listbox and multiple checkboxes

 
Posted: 18 May 2008 07:09 PM   [ # 7 ]   [ Rating: 0 ]
Joined: 2008-05-17
5 posts

Derek Jones, could this become the patch you’re looking for in bug?: http://codeigniter.com/bug_tracker/bug/4530/

I would like to help get a solution to this array problem into CI.

 
Posted: 28 May 2008 05:22 PM   [ # 8 ]   [ Rating: 0 ]
Joined: 2008-04-21
3 posts

If you are trying to use above hack to preserve group of checkboxes and it dosen’t work at all,
just make sure you call set_checkbox() in right way, i.e.

(sorry if someone pointed that earlier)

<input name="id_box[]" type="checkbox" value="1" <?=$this->validation->set_checkbox('id_box''1' ); ?>  />
<
input name="id_box[]" type="checkbox" value="2" <?=$this->validation->set_checkbox('id_box''2' ); ?>  /> 

notice id_box instead id_box[]

 
Posted: 22 June 2008 08:04 AM   [ # 9 ]   [ Rating: 0 ]
Avatar
Joined: 2007-03-07
30 posts

Hi vadivelan,

thanks a lot for your contribution.

I took the liberty to put your code into the followin MY_Validation class, which is working well as far as I can tell.

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

// include native CI_Validation class file
include_once(BASEPATH.'libraries/Validation.php');

/**
 * MY_Validation Class, extends CI_Validation
 *
 * @package     CodeIgniter
 * @subpackage  Libraries
 * @category    Validation
 */
class MY_Validation extends CI_Validation {

    
/**
     * Constructor
     *
     * @access    public
     */
    
public function MY_Validation()
    
{
        parent
::CI_Validation();
        
log_message('debug'"MY_Validation Class Initialized");
    
}

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


    /**
    * Overwrites CI's native validation set_select method to work
    * with arrays.
    *
    * @access   public
    * @param    string
    * @param    string
    * @return   string
    * @author   r.vadivelan / hivelan [.at.] gmail [.dot.] com
    * @link     http://ellislab.com/forums/viewthread/73012/
    */
    
public function set_select($field ''$value '')
    
{
        
if ($field == '' OR $value == '' OR  ! isset($_POST[$field]))
        
{
            
return '';
        
}

        
if(is_array($_POST[$field])) {
            
if(in_array($value,$_POST[$field])) {
                
return ' selected="selected"';
            
}
        } 
elseif ($_POST[$field] == $value{
            
return ' selected="selected"';
        
}

    }

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


    /**
    * Overwrites CI's native validation set_checkbox method to work
    * with arrays.
    *
    * @access   public
    * @param    string
    * @param    string
    * @return   string
    * @author   r.vadivelan / hivelan [.at.] gmail [.dot.] com
    * @link     http://ellislab.com/forums/viewthread/73012/
    */
    
public function set_checkbox($field ''$value '')
    
{
        
if ($field == '' OR $value == '' OR  ! isset($_POST[$field]))
        
{
            
return '';
        
}

        
if(is_array($_POST[$field])) {
            
if(in_array($value,$_POST[$field])) {
                
return ' checked="checked"';
            
}
        } 
elseif ($_POST[$field] == $value{
            
return ' checked="checked"';
        
}
    }

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


    /**
    * Overwrites CI's native validation prep_for_form method to work
    * with arrays. Takes a string or an array and returns the same.
    *
    * @access   public
    * @param    mixed
    * @return   mixed
    * @author   r.vadivelan / hivelan [.at.] gmail [.dot.] com
    * @link     http://ellislab.com/forums/viewthread/73012/
    */
    
public function prep_for_form($data '')
    
{
        
if (is_array($data))
        
{
            
foreach ($data as $key => $val)
            
{
                $data[$key] 
$this->prep_for_form($val);
            
}
        }

        
if ($this->_safe_form_data == FALSE OR $data == '')
        
{
            
return $data;
        
}

        
if(is_array($data)) {
            
return $data;
        
else {
            
return str_replace(array("'"'"''<''>'), array("&#39;""&quot;"'<''>'), stripslashes($data));
        
}
    }

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


    /**
     * native php function caller
     *
     * This function calls native php functions for each values submitted from the form
     *
     * @access  public
     * @param   string
     * @return  string
     * @author  r.vadivelan / hivelan [.at.] gmail [.dot.] com
     * @link    http://ellislab.com/forums/viewthread/73012/
     */
    
public function php_func_caller($rule$data '')
    
{
        
if (is_array($data))
        
{
            
foreach ($data as $key => $val)
            
{
                $data[$key] 
$this->php_func_caller($rule,$val);
            
}
        }

        
if ($data == '')
        
{
            
return $data;
        
}

        
if(is_array($data)) {
            
return $data;
        
else {
            
return $rule($data);
        
}
    }

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

}
// END MY_Validation Class

?> 

cheers,
Thomas

 
Posted: 29 June 2008 04:50 PM   [ # 10 ]   [ Rating: 0 ]
Avatar
Joined: 2008-02-27
14 posts

Welcome Thomas!
Best Wishes
Velan

 Signature 

Validation: Enable CI to validate forms with multiple select (listboxes), checkbox groups, re-select listbox and multiple checkboxes

 
Posted: 14 August 2008 12:28 PM   [ # 11 ]   [ Rating: 0 ]
Avatar
Joined: 2008-07-07
21 posts

Thanks for posting this. I’ve found that the default value works well, the only problem I’m having now is with the error message. If you set the rule for the (say) multiple checkbox field to ‘required’ then the default error message needs changing. So, I did this with:

$this->validation->set_message('required''Please check %s'); 

This can then be adapted by entering the information in the fields array. However, this seems to change the message for all other fields apart from the checkboxes. I then tried setting a callback to validate checkboxes instead of using the ‘required’ rule (so I could set the error message from within the callback function), however, the callback function only seems to run when at least one of the checkboxes is checked. Does anyone have a work around for this?

Many thanks

 
Posted: 15 August 2008 04:46 AM   [ # 12 ]   [ Rating: 0 ]
Avatar
Joined: 2008-07-07
21 posts

Looking closer, the error message returned for the checkbox array with the ‘required’ rule was coming from $lang[‘isset’] rather than $lang[‘required’] (which the other fields with ‘required’ were) (see http://codeigniter.com/wiki/Validation/). This means that to change the error message for the checkbox array with the validation fix and ‘required’ rule you need to use something like:

$this->validation->set_message('isset''Please select at least one %s'); 
 
Posted: 18 August 2008 04:07 PM   [ # 13 ]   [ Rating: 0 ]
Avatar
Joined: 2008-05-08
288 posts

Hello Friends,

how does it look like when we generate dropdowns with the form helper?

are we able to add validation to them?

 
Posted: 20 August 2008 09:48 PM   [ # 14 ]   [ Rating: 0 ]
Avatar
Joined: 2008-07-28
511 posts

I personally vote this going in as a bug. I find (at least myself) every 2 to 3 forms i build out of say 5, require the use of an array data being passed. I was really surprised this wasn’t standard functionality. Thanks for the extension. I look forward to this being standard functionality smile

This also works with the ‘set default values’ hack that has been going around for CI’s Validation library. I know, it probably doesn’t belong there. I just couldn’t justify a hole new helper just for one function.

 Signature 

~ 4 All the Right Reasons ~

 
Posted: 21 August 2008 05:53 AM   [ # 15 ]   [ Rating: 0 ]
Avatar
Joined: 2008-05-08
288 posts

yeah i think it should be standart behavior too:)

 
1 of 2
1