Part of the EllisLab Network
x
 
Create New Page
 View Previous Changes    ( Last updated by Zacharias Knudsen )

Assosiative Arrays via POST

This wiki page is about extending CI Input & Validation libraries to support assosiative arrays sent via post.

before this solution, validating a checkbox value inside a checkbox group wasn’t available, you had to retrieve the value first as an array and then do manual validation.

this wasn’t handy in anyway so I had to write this contribution.

read more about this topic into the original forum thread
http://codeigniter.com/forums/viewthread/51260/ (any comments & bug reports should go there also, please )

Usage and Installation

Usage

I’ve written a small sample controller which illustrates everything for you, just check it out and check the source codes well :)

Don’t be silly and try the sample controller before installing the modified libraries as it won’t work :P

Create a new controller file and call it test.php
fill the following codes:

<?php

class test extends controller{

    
function index(){
    
    $this
->load->library('validation');
    
    
$rules = array(
                
'inputs[textbox]'    => 'trim|required',    
                
'inputs[mycheckbox]' => 'trim|numeric',
     );
     
     
$fields  =  array(
                
'inputs[textbox]'    => 'TextBox',    
                
'inputs[mycheckbox]' => 'MyCheckBox',
     );
     
     
$this->validation->set_fields($fields);
     
$this->validation->set_rules($rules);
     
$this->validation->run();

    
    
    
?>
    
<h1>Testing Form:</h1>
    <
form method="post">
    
    <
center><?=$this->validation->error_string?></center>
    
    <
b>TextBox Sample</b><br />
    <
input type="text" name="inputs[textbox]"  value="<?=$this->validation->value('inputs[textbox]')?>" /> <?=$this->validation->error('inputs[textbox]')?>
    
    
<br /><br />
    
    <
b>Radio Sample</b><br />    
    <
input type="radio" name="inputs[mycheckbox]"  value="1" <? if($this->validation->value('inputs[mycheckbox]') == 1) echo "checked"; ?>  /> 1
    
<input type="radio" name="inputs[mycheckbox]"  value="2" <? if($this->validation->value('inputs[mycheckbox]') == 2) echo "checked"; ?>  /> 2
    
<input type="radio" name="inputs[mycheckbox]"  value="abc" <? if($this->validation->value('inputs[mycheckbox]') == 'abc') echo "checked"; ?>  /> abc
    <?
=$this->validation->error('inputs[mycheckbox]')?>    
    
    
<br /><br />
    
    <
input type="submit" value="Test!" />
    </
form>
    <
hr />
    <
h1>Submitted post data:</h1>
    <
h3>dumping $_POST variable</h3>
    <
pre><? print_r($_POST) ?></pre>
    <
span style="font-size:smaller">You should find some extra keys into the post used by the class, just ignore them!</span>
    <
hr />
    <
h1>Testing submitted values:</h1>
    
$this->input->post('inputs[textbox']) <b>prints</b>  "<?=$this->input->post('inputs[textbox]')?>" <br />
    
$this->input->post('inputs[mycheckbox']) <b>prints</b>  "<?=$this->input->post('inputs[mycheckbox]')?>" <br />
    
    <
hr />
    
    <
h1>Redefining post values...</h1>
    
<?
    $this
->input->set_post('inputs[textbox]' , 'textbox value changed, great it works!');
    
$this->input->set_post('inputs[mycheckbox]' , 'checkbox value changed!');
    
?>
    
    
<h3>dumping $_POST variable</h3>    
    <
pre><? print_r($_POST) ?></pre>

    <
h1>Testing defined values:</h1>
    
$this->input->post('inputs[textbox']) <b>prints</b>  "<?=$this->input->post('inputs[textbox]')?>" <br />
    
$this->input->post('inputs[mycheckbox']) <b>prints</b>  "<?=$this->input->post('inputs[mycheckbox]')?>" <br />
    
        
       
<?
    
    }
    
    
}

?>

Attention!

after applying this contribution you have to note some changes:

1- due to the fact that we can’t use brackets [ ] into a class variable, we can’t access $this->validation->mycheckbox[element1]_error anymore to print the field error, so use $this->validation->error(‘mycheckbox[element1]’) instead.

2- same to echo a value, instead of $this->validation->mycheckbox[element1], use $this->validation->value(‘mycheckbox[element1]’)

3- to redefine a variable inside the $_POST, use $this->validation->set_post(‘mycheckbox[element1]’ , ‘new value here’)

 

Installation

all you need is to create two files under your “application/libraries” folder,
and name them:

MY_Input.php
MY_Validation.php


fill the following codes:

MY_Input.php Codes

<?php

class MY_Input extends CI_Input{

    
function MY_Input()
    
{
        parent
::CI_Input();
    
}


    
/**
     * Fetch an item from the POST array
     *
     * @access    public
     * @param    string
     * @param    bool
     * @return    string
     */
    
function post($index = '', $xss_clean = FALSE)
    
{        
        $value  
= $this->brackets_to_index($index , "post");

        if ( ! isset(
$value))
        
{
            
return FALSE;
        
}

        
if ($xss_clean === TRUE)
        
{
            
if (is_array($value))
            
{
                
foreach($value as $key => $val)
                
{                    
                    $value[$key]
= $this->xss_clean($val);
                
}
            }
            
else
            
{
                
return $this->xss_clean($value);
            
}
        }

        
return $value;
    
}

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

    /**
     * Set an item from the POST array
     *
     * @access    public
     * @param    string
     * @param    bool
     * @return    string
     */
    
function set_post($index = '', $value)
    
{
        
return $this->set_brackets_to_index($index , $value ,  'post');
    
}
    
    
// --------------------------------------------------------------------
    
    /**
     * Fetch an item from the COOKIE array
     *
     * @access    public
     * @param    string
     * @param    bool
     * @return    string
     */
    
function cookie($index = '', $xss_clean = FALSE)
    
{
        $value  
= $this->brackets_to_index($index , "cookie");

        if ( ! isset(
$value))
        
{
            
return FALSE;
        
}

        
if ($xss_clean === TRUE)
        
{
            
if (is_array($value))
            
{
                $cookie
= array();
                foreach(
$value as $key => $val)
                
{
                    $cookie[$key]
= $this->xss_clean($val);
                
}
        
                
return $cookie;
            
}
            
else
            
{
                
return $this->xss_clean($value);
            
}
        }
        
else
        
{
            
return $value;
        
}
    }    
    
    
/*
     * This function gets the value of an "array item" passed via post, get or cookie which is written on the form
     * array[array1][array2][item]
     * @access    public
     * @param    string the form of the array
     * @param    string the method used to send the variable possible values are: "post" , "get" and "cookie" .. default is "post"
     * @return    string
     */
    
    
function brackets_to_index($str , $method="post"){

        
// first we remove the closing bracket ]
        
$str2 = str_replace("]" , "" , $str);
        
// next , we explode the str by opening bracket [
        
$array = explode("[", $str2);

        switch(
$method){
        
default:
            
$value = $_POST;
        break;
        case
"cookie":
            
$value = $_COOKIE;
        break;
        case
"get":
            
$value = $_GET;
        break;
        
}
        
// finally we get the index value from the specified array
        
foreach($array as $key=>$index){
            $value
= $value[$index];
        
}
        $value
= isset($value) ? $value : NULL;
        
$value = ($value === false) ? "" : $value;
        switch(
$method){
        
default:
            
$_POST[$str]   = $value;
        break;
        case
"cookie":
            
$_COOKIE[$str] = $value;
        break;
        case
"get":
            
$_GET[$str]    = value;
        break;
        
}

        
return $value;

    
}



    
function set_brackets_to_index($str , $value, $method = 'post'){

        
// first we remove the closing bracket ]
        
$str2 = $str;
        if(
strpos($str2 , '[') != 0){
        $str2  
= substr($str2 , 0 ,strpos($str2 , '[')) . ']' . strstr($str2 , '['); // add ] after the first index
        
$str2  = "[" . $str2;
        
}
        $str2
= str_replace("]" , "']" , $str2);
        
$str2 = str_replace("[" , "['" , $str2);

        switch(
$method){
        
default:
            
eval( '$_POST'.$str2.' = $value; ');
        break;
        case
"get":
            
eval( '$_GET'.$str2.' = $value; ');
        break;
        case
"file":
            
eval( '$_FILES[\'userfile\'][\'name\']'.$str2.' = $value; ');
        break;
        
}
    }



    
function file($str , $key = "name"){
        
// first we remove the closing bracket ]
        
$str2 = str_replace("]" , "" , $str);
        
// next , we explode the str by opening bracket [
        
$array = explode("[", $str2);

        
$value = $_FILES['userfile'];

        for(
$i = 0 ; $i < count($array) ; $i++){
        
if($i == 0) $value = $value[$key];
        else        
$value = $value[$array[$i]];
        
}

        
return $value;
    
}

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

    /**
     * Set an item from the POST array
     *
     * @access    public
     * @param    string
     * @param    bool
     * @return    string
     */
    
function set_file($index = '', $value)
    {
        
return $this->set_brackets_to_index($index , $value , 'file');
    
}
}
?>

 

MY_Validation.php

<?php

class MY_Validation extends CI_Validation{

var $_value = array();

    function
MY_Validation()
    
{
        parent
::CI_Validation();
    
}
    
// --------------------------------------------------------------------
    
    /**
     * Set Fields
     *
     * This function takes an array of field names as input
     * and generates class variables with the same name, which will
     * either be blank or contain the $_POST value corresponding to it
     *
     * @access    public
     * @param    string
     * @param    string
     * @return    void
     */
    
function set_fields($data = '', $field = '')
    
{    
        
if ($data == '')
        
{
            
if (count($this->_fields) == 0)
            
{
                
return FALSE;
            
}
        }
        
else
        
{
            
if ( ! is_array($data))
            
{
                $data
= array($data => $field);
            
}
            
            
if (count($data) > 0)
            
{
                $this
->_fields = $data;
            
}
        }        
            
        
foreach($this->_fields as $key => $val)
        
{        
//            $this->_value[$key] = ( ! isset($_POST[$key]) OR is_array($_POST[$key])) ? '' : $this->prep_for_form($_POST[$key]);
            
$this->_value[$key] = $_POST[$key];
            
            
/*
            $error = $key.'_error';
            if ( ! isset($this->$error))
            {
                $this->$error = '';
            }
            */
            // USE INSTEAD: $this->error('username');
        
}        
    }
        
    
// --------------------------------------------------------------------
    
    /**
     * Run the Validator
     *
     * This function does all the work.
     *
     * @access    public
     * @return    bool
     */        
    
function run()
    
{
        
// Do we even have any data to process?  Mm?
        
if (count($_POST) == 0 OR count($this->_rules) == 0)
        
{
            
return TRUE;
        
}
    
        
// 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)
        
{
            $fieldO
= $field; // save the original field name;
            
$this->CI->input->brackets_to_index($field);
            
//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 text
            
if ( ! in_array('required', $ex, TRUE) AND strpos($rules, 'callback_') === FALSE)
            
{
                
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'];
                    
}
                    
                    $field
= ( ! isset($this->_fields[$field])) ? $field : $this->_fields[$field];
                    
$this->_error_array[$fieldO] = sprintf($line, $field);    
                
}
                        
                
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)
                
{
                    
if ( ! method_exists($this->CI, $rule))
                    
{         
                        
continue;
                    
}
                    
                    $result
= $this->CI->$rule($_POST[$field], $param);    
                    
                    
// 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];
                            // USE INSTEAD: $this->value('username');
                            
$this->_value[$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;
                    // USE INSTEAD:
                    // $this->error('username');

                    // Add the error to the error array
                    
$this->_error_array[$fieldO] = $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;
    
}
    
    
// --------------------------------------------------------------------
    
    /**
     * Return error message of given field name
     *
     * @access    public
     * @param    string
     * @return    string
     */    
    
function error($field){
        
return $this->_error_array[$field];
    
}

    
// --------------------------------------------------------------------
    
    /**
     * Return passed value of given field name
     *
     * @access    public
     * @param    string
     * @return    string
     */
     
    
function value($field){
        
return $this->_value[$field];
    
}

    
// --------------------------------------------------------------------            
    
    /**
     * Overwrite object values with validation output.
     *
     * @access    public
     * @param    obj
     * @return    obj
     */
     
     
function error_set($field , $error){
         $this
->_error_array[$field] .= $error;
     
}

}
?>


Congratulations, now you are able to access, validate and redefine assosiative arrays elements with no limits!


Category:Contributions -> Libraries -> Miscallenous