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

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 ,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 $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) == 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'$exTRUE) 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'$exTRUE) 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($rule09) == 'callback_')
                
{
                    $rule 
substr($rule9);
                    
$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'$exTRUE) 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