5

I have an array of profile data I need to validate:

$user_group_profiles = $this->input->post('user_group_profiles', TRUE);
foreach ($user_group_profiles as $key => $user_group_profile)
{
    $this->form_validation->set_rules("user_group_profiles[$key][profile_name]", 'Profile Name', 'trim|required');
    $this->form_validation->set_rules("user_group_profiles[$key][birthdate]", 'Birthdate', 'trim|required');

    // TODO: heigth/weight not required, but the validation somehow makes it required
    $this->form_validation->set_rules("user_group_profiles[$key][height]", 'Height', 'trim|greater_than[0]');
    $this->form_validation->set_rules("user_group_profiles[$key][weight]", 'Weight', 'trim|greater_than[0]');
}

Height and weight are option, but when no value is set for those fields, CI validation complains. A var_dump($user_group_profiles); shows this:

array
  'ugp_b33333338' => 
    array
      'profile_name' => string '' (length=0)
      'birthdate' => string '' (length=0)
      'height' => string '' (length=0)
      'weight' => string '' (length=0)

Any ideas what might be wrong?

EDIT 1:

I went into CI's Form_validation library and made $_field_data and public member. When I var_export it after, I got this:

  'user_group_profiles[ugp_833333338][height]' => 
    array
      'field' => string 'user_group_profiles[ugp_833333338][height]' (length=42)
      'label' => string 'Height' (length=6)
      'rules' => string 'greater_than[1]' (length=15)
      'is_array' => boolean true
      'keys' => 
        array
          0 => string 'user_group_profiles' (length=19)
          1 => string 'ugp_833333338' (length=13)
          2 => string 'height' (length=6)
      'postdata' => string '' (length=0)
      'error' => string 'The Height field must contain a number greater than 1.' (length=54)
5
  • 1
    profile_name and birthdate are also empty? Commented May 18, 2012 at 2:52
  • Yes, I just submitted the form without any input to show the structure. Commented May 18, 2012 at 10:01
  • Can I take a look at your HTML markup? Pastebin Commented Jun 1, 2012 at 12:46
  • @StackOverflowNewbie - did my solution below work? Commented Jun 4, 2012 at 7:28
  • @StackOverflowNewbie - how did you go? Commented Jun 6, 2012 at 3:28

2 Answers 2

7
+100

Ok - I've just spent an hour on this - and I've worked out the problem + solution

The issue is that when the variable you are testing is part of an array, CI interprets the field as being set, and thus "contains" a value (even when it is empty). Because that "value" is NOT a number greater than 0 - it fails.

Therefore you'll need to unset the $_POST (NOT $user_group_profiles) variable when it is "empty" so that it passes validation. Note - validation is run on $_POST - that is why you are unsetting $_POST and not $user_group_profiles

So the workaround is this:

$user_group_profiles = $this->input->post('user_group_profiles', TRUE);
foreach ($user_group_profiles as $key => $user_group_profile)
{
     // Set the rules
     $this->form_validation->set_rules($key."[profile_name]", "Profile Name", "trim|required");
     $this->form_validation->set_rules($key."[birthdate]", "Birthdate", "trim|required");
     $this->form_validation->set_rules($key."[height]", "Height", "trim|greater_than[0]");
     $this->form_validation->set_rules($key."[weight]", "Weight", "trim|greater_than[0]");

     // Now check if the field is actually empty
     if (empty($user_group_profile['height']))
     {
         // If empty, remove from array so CI validation doesnt get tricked and fail
         unset($_POST[$key]['height']);
     }
     if (empty($user_group_profile['weight']))
     {
         unset($_POST[$key]['weight']);
     }
}

I've tested this - and it fixes your problem.

You could also program it this way if you dont want to touch the $_POST data:

foreach ($user_group_profiles as $key => $user_group_profile)
    {
         // Set the rules
         $this->form_validation->set_rules($key."[profile_name]", "Profile Name", "trim|required");
         $this->form_validation->set_rules($key."[birthdate]", "Birthdate", "trim|required");


         // Now check if the field is actually empty
         if ( ! empty($user_group_profile['height']))
         {
             $this->form_validation->set_rules($key."[height]", "Height", "trim|greater_than[0]");
         }
         if ( ! empty($user_group_profile['weight']))
         {
             $this->form_validation->set_rules($key."[weight]", "Weight", "trim|greater_than[0]");
         }
    }
Sign up to request clarification or add additional context in comments.

Comments

1

Let's try and break this down into parts. I hope I can help you out here.

I'm assuming you're doing the following for the XSS Filtering with the second "TRUE" argument:

$user_group_profiles = $this->input->post('user_group_profiles', TRUE);

You can actually do the XSS filtering with the form validation rules, or if you prefer filter the post after the rules. See here for my preference:

$this->form_validation->set_rules('profile_name', 'Profile Name', 'xss_clean|trim|required');

So with knowing that now, we can follow the CI convention for their Form Validation Library. It's not necessary to grab the post before using the Form Validation Library because it auto-detects I believe the POST data anyway by the field name. For example:

$this->form_validation->set_rules('profile_name', 'Profile Name', 'trim|required|xss_clean');
$this->form_validation->set_rules('birthdate', 'Birthdate', 'trim|required|xss_clean');
$this->form_validation->set_rules('height', 'Height', 'trim|greater_than[0]|numeric');
$this->form_validation->set_rules('weight', 'Weight', 'trim|greater_than[0]|numeric');

if ($this->form_validation->run() == FALSE) {
    $this->load->view('my_view_where_this_post_came_from');
} else {
    $profile_name = $this->input->post('profile_name');

    //or if you prefer the XSS check here, this:
    //$profile_name = $this->input->post('profile_name', TRUE);

    $birthdate= $this->input->post('birthdate');
    $height= $this->input->post('height');
    $weight= $this->input->post('weight');

    //$user_group_profiles = $this->input->post();

}

I hope this helps!

EDIT: I also just noticed this. If you're trying to grab the entire post array the code is:

$user_group_profiles = $this->input->post(NULL, TRUE); // returns all POST items with XSS filter 
$user_group_profiles = $this->input->post(); // returns all POST items without XSS filter

Not:

 $user_group_profiles = $this->input->post('user_group_profiles');

A good help if you don't know your $_POST names or are confused, you can do this to see if that data is even there! Like this as your first line:

var_dump($_POST);
exit();

2 Comments

The reason I grab the POST variables is because the form is dynamically generated by my application. I can't just add a rule to "height" because it's really "height_0", "height_1", "height_2", etc. -- and I don't know these things in advance. So, I grab the POST, loop thru them and assign rules in each iteration. That's why I said I have an "array of profile data" ....
Also, the reason I'm using $this->input->post('user_group_profiles') is because I do only want to get that part of the POST array.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.