in_array() not working properly using $_POST - php

I'm trying to let the user select multiple countries and then check if the countries he selected are in the array of allowed countries using PHP
I used javascript for multiple options , this is why it is not found in the tags. Otherwise for testing you can put some custom options between the tags. (country codes in this case)
HTML:
<form method="POST" action="">
<select name="countries[]" class="country" multiple></select>
<button type="submit">Submit</button>
</form>
PHP:
<?php
if(isset($_POST['countrylist'])) {
$arr = array("FR","GF","PF","TF","GE","DE","GI","GR","GL","HK","IS","IN","ID","IE","IL","IT","JP","JO","KZ","KR","LV","LB","LI","LT","LU","MK","MX","MD","MC","MN","MS","MA","NP","NL","NZ","NO","PK"); //These are allowed country codes which are sent by the user the same way as above using POST request. The sent array looks fine as you can see in the var_dump result below.
$array2 = (array) $_POST['countries'];
$array2= array_filter($array2);
if(!in_array($array2, $arr)) {
echo var_dump($array2);
}
}
?>
The in_array() function doesn't seem to work , my var_dump result looks something like this:
array(1) { [0]=> string(2) "FR" } //If I selected France country for example.

$arr is an array of strings. $array2 is an array of strings (just one string in this case).
You are using $array2 as your needle, so you are asking "Does this array appear in this set of strings", which is doesn't, because the array isn't a string.
You would need to do something more like in_array($array2[0], $arr).
That, of course, misses the point since you want to accept multiple values, but it is a place to start.
You need to loop over $array2 and test each value in turn until you get to the end or hit a failure state. You might also look at using array_filter again, this time passing a callback.

in_array() works just fine but you call with wrong arguments. The first argument that it expects is a value to search in the second argument (that must be an array).
Since you have an array of values that you want to search you can either try to search each value at a time using in_array() or you can use array_intersect() to find the values that are present in both arrays.
Your choice will be influenced by the way you decide to handle the unexpected values in the input.
Example using in_array():
$knownValues = ['FR', 'GF', 'PF', 'TF'];
if (! is_array($_POST['countries'])) {
// The input does not look valid; there is nothing to process
// Handle this in the most appropriate way for your application and stop here
// return/exit/throw/whatever
}
$valid = [];
foreach ($_POST['countries'] as $countryId) {
if (! in_array($countryId, $knownValues)) {
// $countryId is not a valid/known country code
// Do something with it (report it, ignore it etc.)
continue;
}
$valid[] = $countryId;
}
// Here $valid contains the input values that are present in $knownValues
Example using array_intersect():
$knownValues = ['FR', 'GF', 'PF', 'TF'];
if (! is_array($_POST['countries'])) {
// The input does not look valid; there is nothing to process
// Handle this in the most appropriate way for your application and stop here
// return/exit/throw/whatever
}
$valid = array_intersect($_POST['countries'], $knownValues);
$invalid = array_diff($_POST['countries'], $knownValues);
// The known/valid and unknown/invalid values have been separated
// Do whatever you want with them.

Related

Get value out of Array

I am trying to get a certain value out of an array.
Example of the array is:
array(2) {
["error"]=>
array(0) {
}
["result"]=>
array(1) {
["open"]=>
array(1) {
["12345-AAAAA-66AAKK"]=>
array(14) {
["inf"]=>
Usually when I want a certain value I would use:
$datawanted=$data[result][open][value];
However, in this case the first array is a variable that always changes (12345-AAAAA-66AAKK), I need to find the value of that.
I tried getting this with reset() and key[0] but this not give the wanted result.
Is there a way to get the output of the first element in the result array?
You can use array_search: http://php.net/manual/de/function.array-search.php
Example:
foreach ($array['result']['open'] as $dynamicKey => $item) {
if ($key = array_search('Value you are looking for', $item) {
$datawanted=$array['result']['open'][$dynamicKey][$key];
}
}
$data[result][open] is not a correct way to access array items.
The token result looks like a constant. PHP searches for a constant named result, cannot find one and triggers a notice. Then it thinks "I guess the programmer wanted to write 'result' (a string, not a constant). I'll convert it as string to them." and uses 'result' instead.
It works but it's a horrible practice. It dates from the prehistory of PHP, 20 years ago and it's not recommended.
After you fix your code to correctly denote the keys of an array, the next step is to pick one of the many PHP ways to access values in the array.
You can get the first value of an array without knowing its key ($data['result']['open']['12345-AAAAA-66AAKK']) by using the function reset():
$datawanted = reset($data['result']['open']);
Or you can use the function array_values() to get only the values of the array (the keys are ignored, the returned array have the values indexed from zero) then your desired data is at position 0 on this array:
$values = array_values($data['result']['open']);
$datawanted = $values[0];
Another option, if you don't need to keep $data for further processing, is to use the PHP function array_shift() to remove the first value from the array and return it. Be warned that this function modifies the array it receives as argument:
$datawanted = array_shift($data['result']['open']);
If you need to process all the values of $data['result']['open'] (and you probably do) then the best way is to use the foreach PHP statement. It allows you to access both the key and the value of each element of the array:
foreach ($data['result']['open'] as $key => $value) {
// $key is '12345-AAAAA-66AAKK'
$datawanted = $value;
}

What is the purpose of associative array

I am new to this array in forms. I tried to get rid of the associative array in this line
("F001"=>"a","F002"=>"b","F003"=>"c","F004"=>"d","F005"=>"e","F006"=>"f","F007"=>"g","F008"=>"h","F009"=>"i","F010"=>"j")
and made it ("F001", "F002" and so on) but program wont work. If I put it back it will work. My question is why it wont work if i get rid of the associative array?
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<?php
if (isset($_POST['search'])) {
// move $students into the if statement cause we won't
// need it unless they're searching
$students = array (
array ("F001"=>"a","F002"=>"b","F003"=>"c","F004"=>"d","F005"=>"e","F006"=>"f","F007"=>"g","F008"=>"h","F009"=>"i","F010"=>"j"),
array ("albert","berto","charlie","david","earl","francis","garry","harry","irish","james"),
array (1,2,3,3,2,1,2,1,3,1)
);
$idNumber = $_POST['search'];
// we can use isset here because the student id *is* the key.
// if it was the value, than we would use array_search() and
// check if it returned false
if (isset($students[0][$idNumber])) {
// array_keys returns the keys of an array as an array,
// allowing us to find the numerical index of the key
$studentIndex = array_search($idNumber,array_keys($students[0]));
// printf basically allows for formatted echoing. %s means
// a string. %d means a number. You then pass in your
printf('Student ID: %s<br>Name: %s<br>Grade: %d', $idNumber, $students[1][$studentIndex], $students[2][$studentIndex]);
}
else {
// use htmlspecialchars() to encode any html special characters cause never trust the user
printf('No student with ID "%s" found.', htmlspecialchars($idNumber));
}
}
?>
<form action="" method="POST">
Id number: <input type="text" name="search">
<input type="submit" value="search">
</form>
</body>
</html>
Why it doesn't work if you remove it is mentioned in the comments:
// we can use isset here because the student id *is* the key.
// if it was the value, than we would use array_search() and
// check if it returned false
The reason behind that decision isn't clear from the example, but the letters those keys represent could have a wider meaning to a bigger system, and therefore a decision was taken to make it associative.
As for the purpose of an associative array, it can make searching for specific items simpler, especially in multi-dimensional arrays. It also can improve readability.
Trying to understand the following would be a pain at best:
$posts[0][1][0][7][4] = 'value';
Where as understanding the below is a little easier:
$posts[newest][1][information][tags][4] = 'value';
The use of associative arrays above make it easier to see that in an array of posts, the newest post with index 1 has information, and the 5th tag (because of 0 indexing) is 'value'.

Compare PHP arrays

I know there are a lot of these, but I'm looking for something slightly different.
A straight diff won't work for me.
I have a list (array) of allowed tags i.e. ["engine","chassis","brakes","suspension"]
Which I want to check with the list the user has entered. Diff won't work, because the user may not enter all the options i.e. ["engine"] but I still want this to pass. What I want to happen is fail if they put something like "banana" in the list.
You can use array_intersect(), and check the size of the resulting array with the size of the input array. If the result is smaller, then the input contains one or more items not in the 'allowed' array. If its size is equal, all items in it are in the user's input, so you can use the array do do whatever you want.
Use array_diff();
$allowed=array("engine","chassis","brakes","suspension");
$user=array("engine","brakes","banana");
$unallowed=array_diff($user, $allowed);
print_r($unallowed);
This will return banana, as it is in $user, but not in $allowed.
array_diff(): http://nl.php.net/array_diff
Returns an array containing all the entries from array1 that are not present in any of the other arrays.
if ( array_diff( $input, $allowed ) ) {
// error
}
$allowed_tags = array("engine","chassis","brakes","suspension");
$user_iput = array("engine", "suspension", "banana");
foreach($user_input as $ui) {
if(!in_array($ui, $allowed_tags)) {
//user entered an invalid tag
}
}

Extracting Data from JSON Using PHP

Here's a test jason feed
{"MEMBERS":[{"NAME":"Joe Bob","PET":["DOG"]}, {"NAME":"Jack Wu","PET":["CAT","DOG","FISH"]}, {"NAME":"Nancy Frank","PET":["FISH"]}]}
What I'm attempting to do is extract data if PET contains CAT or FISH or both. Another user suggested a filter as such:
$filter = array('CAT', 'FISH');
// curl gets the json data (this part works fine but is not shown for brevity)
$JSONarray=json_decode($JSONdata,true);
foreach($JSONarray['MEMBERS'] as $p) {
if (in_array($p['PET'], $filter)) {
echo $p['NAME'] . '</br>';
}
}
But it's not returning anything.
Note: edited based on comments below
Use strings to access the array and not uninitialized constants.
$p['PET'] is an array. You have to use some other method to compare it against $filter, e.g. array_intersect:
foreach($JSONarray['MEMBERS'] as $p) {
$diff = array_intersect($filter, $p['PET']);
if (!empty($diff)) {
echo $p['NAME'].'</br>';
}
}
DEMO
It should work like this:
foreach($JSONarray['MEMBERS'] as $p) {
if (array_diff($p['PET'], $filter) != $p['PET']) {
echo $p['NAME'].'</br>';
}
}
Remember to always use quotes when you are trying to access an element of an associative array. Without quotes, PHP tries to interpret it as a constant (throwing a Notice on failure). So instead of $a[index] do $a['index']. Please also see Why is $foo[bar] wrong?
In your code, $p['PET'] will be an array of pet names, not one pet name. Testing with in_array() won't be successful, because it will try to find the whole array in $filter. In my code example, I used array_diff() which will find the difference between the two arrays, then I compare it to the original array. If they match, the $filter pets were not found.
First, you need to use quotes on your array keys:
$JSONarray['MEMBERS']
$p['PET']
$p['NAME']
Secondly, you can't use in_array as it assumes 'needle' to be the array('CAT', 'FISH') and not any one of it's values.
(The parameter order was also the other way around)
Here's a method using array_intersect:
foreach($JSONarray['MEMBERS'] as $p) {
$test = array_intersect($filter, $p['PET']);
if (count($test)>0) {
print( $p['NAME'].'</br>' );
}
}

A $_GET input parameter that is an Array

I'm trying to pass 3 parameter to a script, where the 3rd parameter $_GET['value3'] is supposed to be an array
$_GET['value1']
$_GET['value2']
$_GET['value3'] //an array of items
I'm calling the script like this: (notice my syntax for value3, I'm not sure it's correct)
http://localhost/test.php?value1=test1&value2=test2&value3=[the, array, values]
I then use a foreach to hopefully loop through the third parameter value3 which is the array
//process the first input $_GET['value1']
//process the second input $_GET['value2']
//process the third input $_GET['value3'] which is the array
foreach($_GET['value3'] as $arrayitem){
echo $arrayitem;
}
but I get the error Invalid argument supplied for foreach()
I'm not sure if my methodology is correct. Can some clarify how you'd go about doing the sort of thing
There is no such thing as "passing an array as a URL parameter" (or a form value, for that matter, because this is the same thing). These are strings, and anything that happens to them beyond that is magic that has been built into your application server, and therefore it is non-portable.
PHP happens to support the &value3[]=the&value3[]=array&value3[]=values notation to automagically create $_GET['value3'] as an array for you, but this is special to PHP and does not necessarily work elsewhere.
You can also be straight-forward and go for a cleaner URL, like this: value3=the,array,values, and then use explode(',', $_GET['value3']) in your PHP script to create an array. Of course this implies that your separator char cannot be part of the value.
To unambiguously transport structured data over HTTP, use a format that has been made for the purpose (namely: JSON) and then use json_decode() on the PHP side.
try
http://localhost/test.php?value1=test1&value2=test2&value3[]=the&value3[]=array&value3[]=values
For arrays you need to pass the query parameters as
value3[]=abc&value3[]=pqr&value3[]=xyz
You can cast the name of the index in the string too
?value1[a]=test1a&value1[b]=test1b&value2[c][]=test3a&value2[c][]=test3b
would be
$_GET['value1']['a'] = test1a
$_GET['value1']['b'] = test1b
$_GET['value2']['c'] = array( 'test3a', 'test3b' );
http://php.net/manual/en/reserved.variables.get.php
Check out the above link..
You will see how the GET method is implemented.
What happens is that the URL is taken, it is delimited using '&' and then they are added as a key-value pair.
public function fixGet($args) {
if(count($_GET) > 0) {
if(!empty($args)) {
$lastkey = "";
$pairs = explode("&",$args);
foreach($pairs as $pair) {
if(strpos($pair,":") !== false) {
list($key,$value) = explode(":",$pair);
unset($_GET[$key]);
$lastkey = "&$key$value";
} elseif(strpos($pair,"=") === false)
unset($_GET[$pair]);
else {
list($key, $value) = explode("=",$pair);
$_GET[$key] = $value;
}
}
}
return "?".((count($_GET) > 0)?http_build_query($_GET).$lastkey:"");
}
Since, they are added as a key-value pair you can't pass array's in the GET method...
The following would also work:
http://localhost/test.php?value3[]=the&value3[]=array&value3[]=values
A more advanced approach would be to serialize the PHP array and print it in your link:
http://localhost/test.php?value3=a:3:{i:0;s:3:"the";i:1;s:5:"array";i:2;s:6:"values";}
would, essentially, also work.

Categories