Functionally clueless - please help

Hi all,

I’ve have this function but I don’t know how to “call it” or use it in any sort of way - I’m not that clued up when it comes to functions.

I am setting integers for checkbox values instead of strings and this function is supposed to compare the submitted values to those in an array. I “checked” a few checkboxes, following which I then submitted the form. But how do I access the values? How do I access the compared values in the $valid_sports array?

In addition, I’ll probably also have checkboxes with different names such as sports, food, education etc. How can I use this one function to validate all of these differently-named checkboxes?

Thank you! Any assistance will be great.

Herewith the function:

<?php

function validate_sports() {
  $sports = array(1 => 'tennis', 'surfing', 'football', 'athletics');
  $valid_sports = array();

  if (isset($_POST['sports'])) {
    foreach ($_POST['sports'] as $post_sports) {
      foreach ($sports as $sport) {
        if ($post_sports === $sport) {
          $valid_sports[] = $sport;
          break;
        }
      }
    }

    if ($_POST['sports'] === valid_sports) {
      return true;
    }
  }

  return false;


}


?>

Well lets be upfront first. You really should only be defining functions if you need to call a piece of code repeatedly. (Some people may use them for organizational tools as well, but that’s a more advanced topic of modelling your code.)

How do you call a function? The same way you call all the other functions you’re invoking in your script. array() is a function(-ish). isset() is a function.So, you’ve named your function validate_sports, and you dont pass it any parameters. You return a boolean (true or false), so the function can be invoked into a variable…


$valid = validate_sports();

or straight into a comparitor


if(validate_sports()) {

I am setting integers for checkbox values instead of strings and this function is supposed to compare the submitted values to those in an array. I “checked” a few checkboxes, following which I then submitted the form. But how do I access the values? How do I access the compared values in the $valid_sports array?

Inside or outside the function?
If inside, the elements of the $valid_sports array are numerically indexed from 0. You can access them via a FOREACH as you have already shown you know how to do, or by directly accessing them by key. The first valid sport would be $valid_sports[0], the next $valid_sports[1], etc.
OUTSIDE the function, the $valid_sports array is no longer accessible due to variable scope. If you want to keep track of the valid results outside your function, return the valid array instead of the true/false.

In addition, I’ll probably also have checkboxes with different names such as sports, food, education etc. How can I use this one function to validate all of these differently-named checkboxes?

Pass the name of your target in as a parameter to the function. You’ll probably want to pass a “valid array” parameter as well.

PS: You have a typo in your final IF. Spot the missing $.

To elaborate on this, it’s a good idea to extract the more general aspects of your code into functions. This makes the code more easily reusable, reducing duplication. For example, you might replace your validate_sports() function with something like this:


function get_valid_elements(array $input, array $valid_elements)
{
    $keys = array_keys($input);
    return array_intersect($keys, $valid_elements);
}

// Example of usage
$valid_sports = array('tennis', 'surfing', 'football', 'athletics');
$sports = get_valid_elements($_POST['sports'], $valid_sports);

Notice that this function doesn’t know anything about the $_POST var, it doesn’t care where the data comes from. If you wanted to use data from $_GET you wouldn’t need to modify the function.

Hi StarLion and fretburner!

Thank you for all of the information - I really appreciate the assistance, on a Sunday no less. :slight_smile:

@StarLion, I have been playing around with the function but for some reason I always get boolean false. I must be doing something wrong. In my code, my function definition appears first, then my form with the checkboxes and then I have this line:

$valid = validate_sports(); if (isset($valid)){ var_dump($valid);}

I have 4 checkboxes, with tennis having a value=“1”, surfing 2, football 3, and athletics 4, to match that of the $sports array. After checking all of the checkboxes, I submit the form and receive “boolean false” using var_dump. Not sure why.

PS: You have a typo in your final IF. Spot the missing $.

Got it, thanks.

@fretburner,

it’s a good idea to extract the more general aspects of your code into functions. This makes the code more easily reusable, reducing duplication

Yes, I probably do have some code that would be better off in one or more functions.

For example, you might replace your validate_sports() function with something like this:

Thank you, that looks very useful. I’ll try it and will let you know.

Cheers for now.

Well, lets look at your code.


<?php 

function validate_sports() {
  $sports = array(1 => 'tennis', 'surfing', 'football', 'athletics');
  $valid_sports = array();

  if (isset($_POST['sports'])) {
    foreach ($_POST['sports'] as $post_sports) {
      foreach ($sports as $sport) {
        if ($post_sports === $sport) {
          $valid_sports[] = $sport;
          break;
        }
      }
    }

    if ($_POST['sports'] === valid_sports) {
      return true;
    }
  }

  return false;


}

So the thrust of your function revolves around this:
foreach ($_POST[‘sports’] as $post_sports) {
foreach ($sports as $sport) {
if ($post_sports === $sport) {

But… what are you actually putting into those values? Let’s look closer.

$sports = array(1 => ‘tennis’, ‘surfing’, ‘football’, ‘athletics’);
So this creates the following array structure:
Array ( [1] => tennis [2] => surfing [3] => football [4] => athletics )
$_POST[‘sports’] is defined by your form, but based on the above statement, we come out with something that looks like:
Array ( [0] => 1 [1] => 3 [2] => 4)

So when running:
The outer Foreach pulls the first entry of the $_POST array… which is 1.
The inner Foreach pulls the first entry of the sports array…which is “tennis”.
“tennis” !== 1, so false. (By now you should see the problem, and shouldnt need to continue to iterate your loop manually)

Either your form needs to change, or your comparitor array needs to change.

Thanks for all of that, but I still haven’t got the foggiest idea what I should be doing.

Either your form needs to change, or your comparitor array needs to change

Could you please demonstrate how?

Hi fretburner, I tried your code but I get “Undefined index: sports”. Must I first check if the form has been submitted? I used

if(!empty($sports))var_dump($sports);

but $sports is always empty.


function get_valid_elements(array $input, array $valid_elements)
{
    $keys = array_keys($input);
    return array_intersect($keys, $valid_elements);
}

// Example of usage
$valid_sports = array('tennis', 'surfing', 'football', 'athletics');
$sports = get_valid_elements($_POST['sports'], $valid_sports); 

Thank you. Hey, at least I’m living up to the thread title.

Yes, you need to check that $_POST[‘sports’] is actually set. I know you’d included that check in your original function but, as I mentioned before, I think the function is more flexible if it doesn’t know anything about where the data is coming from.

Also, the function I wrote is wrong… I’d missed what you said about using integers for the form values. That being the case, the function could be rewritten along these lines:


function get_valid_elements($input, array $valid_elements)
{
    if ($input) {
    	return array_intersect_key($valid_elements, array_flip($input));
    } else {
    	return null;
    }
}

The function works by using array_flip to turn the input integers into array keys, which are then compared to the keys of the array of valid elements. Only those which match are returned, filtering out any invalid values.

An example of the calling code:


// Lets say $_POST['sports'] = array(1, 3, 6);
$sports = isset($_POST['sports']) ? $_POST['sports'] : false;

$valid_sports = array('tennis', 'surfing', 'football', 'athletics');
$sports = get_valid_elements($sports, $valid_sports);

// $sports is now:
// Array
// (
//     [1] => surfing
//     [3] => athletics
// )

Is that the kind of thing you’re after?

fretburner always writes some nice code, but I will say this…
If you are building the FORM with these same “valid” arrays then just use the posted keys to grab names.

<html>
<body>
<?php
 function get_valid_elements(array $input, array $valid_elements)
{
	$selected_fields = array();
	foreach($input as $key){	
		$selected_fields[] = $valid_elements[$key];	
	}
    return $selected_fields;
}

$valid_sports = array('tennis', 'surfing', 'football', 'athletics');
$valid_food = array('meat', 'vegetable', 'grain', 'dairy');
$valid_education = array('Grade School', 'Jr High', 'High School', 'Collage');


if(isset($_POST['submit'])){
	//Get names from keys
	$sports = get_valid_elements($_POST['sports'], $valid_sports);
	$food = get_valid_elements($_POST['food'], $valid_food);
	$education = get_valid_elements($_POST['education'], $valid_education);
	
	// do what you wish with results
	echo "<pre>";   	
	print_r($sports);	   	
	print_r($food);   	
	print_r($education);
	echo "</pre>";	
}

//Sample form
echo "<form method=\\"post\\" action=\\"\\">\\r";
echo "Sports<br />\\r";
foreach($valid_sports as $skey => $svalue){
	echo "<input type=\\"checkbox\\" name=\\"sports[]\\" value=\\"" . $skey . "\\" />" . $svalue . "<br />\\r";
}
echo "Food<br />\\r";
foreach($valid_food as $fkey => $fvalue){
	echo "<input type=\\"checkbox\\" name=\\"food[]\\" value=\\"" . $fkey . "\\" />" . $fvalue . "<br />\\r";
}
echo "Education<br />\\r";
foreach($valid_education as $ekey => $evalue){
	echo "<input type=\\"checkbox\\" name=\\"education[]\\" value=\\"" . $ekey . "\\" />" . $evalue . "<br />\\r";
}
echo "<input type=\\"submit\\" name=\\"submit\\" value=\\"Submit\\" />\\r";
echo '</form>';
?>
</body>
</html>

And fretburner’s function example works perfectly to replace what I did…

function get_valid_elements($input, array $valid_elements)
{
    if ($input) {
        return array_intersect_key($valid_elements, array_flip($input));
    } else {
        return null;
    }
} 

Cheers Drummin :slight_smile:

Yeah that’s another way to go about it. There are usually several ways to skin a cat with PHP.

One thing I would mention about your example though Drummin, is that you’d still need to check that the various POST vars are set. If the user doesn’t select any sports then your function is going to cause an error, as $input is type-hinted as an array.

One thing I would mention about your example though Drummin, is that you’d still need to check that the various POST vars are set. If the user doesn’t select any sports then your function is going to cause an error, as $input is type-hinted as an array.

Yes correct.

I’m going to have to start using array_intersect more as I tend to build things the hard way, but like you said “there are usually several ways to skin a cat.” Always learning.

Is that the kind of thing you’re after?

Yes, it’s working great now, thank you so much! :slight_smile: The one thing I did have to change is how the checkbox values are numbered. The first checkbox must have a value of 0, instead of 1.

Can I ask you something? I am using the compared values and/or keys in a query. With regards to security, must I employ some additional measure or can I just use these values/keys as is in the query? I’m just double-checking.

Thanks.

@Drummin,

hi Drummin, thanks a lot for your help as well!