Using array_flip With or Without a Value - php

Code used for processing form $_POST submissions is working well on most forms but suddenly broke on a new set of forms. I can't see any difference in the forms themselves as it's based purely on the posted values and I have it fixed but I am curious why the sudden problem.
There are some cases where specific post values are not to be processed and those, when they are not needed, are in $RemoveFields as a comma-separated list which is converted to an array and on the one set of forms, it doesn't matter if $RemoveFields has any value or not but on the other set it crashes when empty.
By adding a conditional I was able to make it work but can anyone tell me what the problem is on the original code? Both the old and new are below. The first works on only some of the forms while the second seems to work on all.
The original code:
// Remove unneeded fields specified in $RemoveFields variable
if (isset($RemoveFields) && !is_array($RemoveFields)) $RemoveFields = array($RemoveFields);
$filteredarray = array_diff_key($_POST, array_flip($RemoveFields));
The same code but with a conditional for the $filteredarray value:
// Remove unneeded fields specified in $RemoveFields variable
if (isset($RemoveFields) && !is_array($RemoveFields)) $RemoveFields = array($RemoveFields);
$filteredarray = (isset($RemoveFields)) ? array_diff_key($_POST, array_flip($RemoveFields)) : $_POST;

In the original code, you call array_flip($RemoveFields) even when $RemoveFields is not set. This fails because the argument to array_flip() must be an array.
You should use isset() to protect both lines of code:
if (isset($RemoveFields)) {
if (!is_array($RemoveFields)) {
$RemoveFields = array($RemoveFields);
}
$filteredarray = array_diff_key($_POST, array_flip($RemoveFields));
} else {
$filteredarray = $_POST;
}

Related

Check if $_POST is empty

I realize this question has been asked multiple times, but none have resolved the issue for me.
I want to check if any values in the $_POST array are empty except for two (sHostFirstName and sHostLastName), and throw a 400 error if there is an empty value. The only way I can get it to throw the 400 error is by putting a die() command after the header command, however I get the 400 error no matter if there are empty values or not.
foreach ($_POST as $key => $value) {
if (empty($value) || !isset($value) && $key != 'sHostFirstName' || 'sHostLastName') {
header("HTTP/1.1 400 Bad Request");
break;
}
}
isset() will return true if the variable has been initialised. If you have a form field with its name value set to userName, when that form is submitted the value will always be "set", although there may not be any data in it.
Instead, trim() the string and test its length
if("" == trim($_POST['userName'])){
$username = 'Anonymous';
}
There's no need to loop through your POST data. Store your POST data in a variable $postData and remove the keys sHostFirstName and sHostLastName since these two need not be checked.
This $postData contains all key value pairs which need to be checked for blank entries. Now, use array_filter() to filter out any blank entries and store it in $filteredArray.
Finally, if there were no blank entries, the length of $postData will be same as ``$filteredArray`. If lengths don't match, that will imply one or more array keys had been filtered.
$postData = $_POST;
unset($postData['sHostFirstName'], $postData['sHostLastName']); // $postData contanis all key value pairs which can't be empty
$filteredArray = array_filter($postData); // Filters out the blank entries
/* If the length of `$filteredArray` and `$postData` aren't the same, that means one or more fields had been filtered out */
if (count($filteredArray) != count($postData)) {
header("HTTP/1.1 400 Bad Request");
}
Something like this
//store and set default if not set - only needed for checkbox or radio buttons. for example, text fields are always submitted as an empty string.
$sHostFirstName = isset($_POST['sHostFirstName']) ? $_POST['sHostFirstName'] : false;
unset($_POST['sHostFirstName']); //remove so it's not part of our count
//store and set default if not set - only needed for checkbox or radio buttons.
$sHostLastName = isset($_POST['sHostLastName']) ? $_POST['sHostLastName'] : false;
unset($_POST['sHostLastName']); //remove so it's not part of our count
$post = array_filter(array_map('trim', $_POST)); //copy post remove empty items.
if( count( $post ) != count($_POST)
//if count $_POST is not the same as count $post ( empty removed via array_filter) then something was removed / empty
header('HTTP/1.1 400 Bad Request', true, 400);
exit();
}
should do after unset is used on them. See,
store them in variables
remove them from post
then remove empty from a copy of post
count copy ( - empties ) and compare to count of original
if the count is different then something was removed ( ie. empty )
no need for a loop.
Also you can send the optional 2nd and 3rd params for header:
http://php.net/manual/en/function.header.php
2nd = replace - The optional replace parameter indicates whether the header should replace a previous similar header, or add a second header of the same type. By default it will replace, but if you pass in FALSE as the second argument you can force multiple headers of the same type.
3rd = http_response_code - Forces the HTTP response code to the specified value. Note that this parameter only has an effect if the string is not empty.

Validating bunch of form data in php - Is it necessary?

I am making a survey website. I just want to know if it's really necessary to validate each and every POST data into the database by using isset and !empty. I have around 30 columns and I find it redundant.
Is there any cleaner way than this?
EDIT:
And how about if I have optional fields? How do I come about that?
You can do this such way:
PHP 5.5:
if(!empty(array_filter($_POST)))
{
//there are non-empty fields in $_POST
}
PHP <5.5:
$filtered = array_filter($_POST);
if(!empty($filtered))
{
//there are non-empty fields in $_POST
}
this difference is because before PHP 5.5 empty() was not able to accept non-variables (i.e. expressions, for example)
Edit: if you have some optional fields, then you can deal with this, for example, with having list of mandatory fields:
$array = ['one'=>36, 'two'=>null, 'three'=>'data', 'four'=>0];
$mandatory = ['one', 'three'];
$data = array_intersect_key($array, array_flip($mandatory));
if(!empty($data))
{
//all mandatory fields are not empty
}

PHP: If condition with explode within foreach loop

I am trying to get multiple value from user input from text field and want to explode or keep adding into if condition statement
Here is my code
foreach ($list['post'] as $item) {
if( ($item['single']['catid'] != 8) AND ($item['single']['catid'] != 4) ){
$this->list_post($item);
}
}
Now what exactly I am looking for is in if( ($item['single']['catid'] != 8) AND ($item['single']['catid'] != 4) ) I want allow user to add multiple category ID and each ID will add AND and further id code AND ($item['single']['catid'] != 4)
I never done this before and don't know either this is proper way to do or any other possible better way.
Thanks a lot
You should have some kind of an array of the category IDs you want to check for, for example:
$categories = array(8, 4);
Then you could use something like the in_array(needle, haystack) built-in function of PHP.
Your if condition would become like that one: if (!in_array($item['single']['catid'], $categories)) {.
You should be using the above, but I am going to give you an idea of how it works, so you can understand the principle for more complex issues:
function exists($target, $array) {
foreach ($array as $element) { // Go through each element in the array
if ($element == $target) { // Check to see if any element there is what you are searching for
return true; // Return true, that it does exist, and stop there.
} else {
// Just ignore it...
}
}
return false; // If you get here, it means nothing returned true, so it does not exist...
}
To be used as if (exists($item['single']['catid'], $categories)) {.
It wouldn't work if it was "inside" the if statement because you have to do some processing before evaluating if it exists or not. So you either could have done that before the if statement, and store the result in a variable, or use a function (which PHP provides).
Hopefully the concept will help you fir more complex problems...
Note: this assumes your input is in the form of an array, which you can build via various ways, if not provided as is directly.
Update:
The input you get via the input field is sent through form, to which you specify either POST or GET as a method. Assuming it is POST that you are using, this is how you'd get the input as a string as it was entered in the text field:
$categories_string = $_POST['the_name_field_in_the_input_tag'];
After that you have to understand it as a list of items, let's say separated by commas: 1,3,5,8. Then this is simply separating by commas. You can use explode($delimiter, $string). Like that:
$categories_array = explode(',', $_POST['categories']);
But you cannot trust the input, so you could get something like 1, 2, 3,5,6. The spaces will mess it up, because you will have spaces all around. To remove them you can use trim for example.
$categories = array(); // Create the array in which the processed input will go
foreach ($categories_array as $c) { // Go through the unprocessed one
$categories[] = trim($c) * 1; // Process it, and fill the result. The times one is just so that you get numbers in the end and not strings...
}
Then you can use it as shown earlier, but keep in mind that this is just an example, and you might not even need all these steps, and there are much more efficient ways to process this input (regular expressions for example). But the concern here is not sanitizing input, but keep in mind you will need to do that eventually.
Hope it's clear enough :)
You might be better off with in_array() for checking a value against a variable number of possibilities.
I'm not sure I understand your problem. You want user to be able to input different values, e.g.:
$string = "5, 6, 7, 8, 10";
Afterwards, you want to check if 'catid' is not in that array and if it isn't you want to run $this->list_post($item);
If so, then you should use something like this:
$values = explode(", ", $string); //make array from values
foreach ($list['post'] as $item) {
if (!in_array($item['single']['catid'], $values)) { //check whether catid is in array
$this->list_post($item); // execute whatever you want
}
}
Hope it helps.

PHP isset not working properly on form, with loops and arrays

This is honestly the most finicky and inept language I've ever coded in. I'll be glad when this project is good and over with.
In any case I have to us PHP so here's my question.
I have an Array named $form_data as such:
$form_data = array
('trav_emer_med_insur',
'trav_emer_single',
'trav_emer_single_date_go',
'trav_emer_single_date_ba',
'trav_emer_annual',
'trav_emer_annual_date_go',
'trav_emer_extend',
'trav_emer_extend_date_go',
'trav_emer_extend_date_ef',
'trav_emer_extend_date_ba',
'allinc_insur',
'allinc_insur_opt1',
'allinc_single_date_go',
'allinc_single_date_ba',
'allinc_insur_opt2',
'allinc_annual_date_go',
'allinc_annual_date_ba',
'cancel_insur',
'allinc_annual_date_go',
'allinc_annual_date_ba',
'visitor_insur',
'country_select',
'visitor_supervisa',
'visitor_supervisa_date_go',
'visitor_supervisa_date_ba',
'visitor_student',
'visitor_student_date_go',
'visitor_student_date_ba',
'visitor_xpat',
'visitor_xpat_date_go',
'visitor_xpat_date_ba',
'txtApp1Name',
'txtApp2Name',
'txtApp1DOB',
'txtApp2DOB',
'txtApp1Add',
'txtApp1City',
'selprov',
'txtApp1Postal',
'txtApp1Phone',
'txtApp1Ext',
'txtApp1Email',
'conpref', );
These are the names of name="" fields on an HTML form. I have verified that ALL names exist and have a default value of '' using var_dump($_POST).
What I want to do is very simple, using the $form_data as reference do this:
create a new array called $out_data which can handle the data to display on a regurgitated form.
The structure of $out_data is simple the key will be the name of the element from the other array $out_data[txtApp1Name] for example, and then the value of that key will be the value.
Now what I want is to first check to see if every name="" is set or not, to eliminate errors and verify the data. Then regardless of whether it is set or not, create its placeholder in the $out_data array.
So if $_POST[$form_data[1]] (name is 'trav_emer_single') is not set create an entry in $out_data that looks like this $out_data([trav_emer_single] => "NO DATA")
If $_POST[$form_data[1]] (name is 'trav_emer_single') is set create and entry in $out_data that looks like this: $out_data([trav_emer_single] => "whatever the user typed in")
I have tried this code:
$out_data = array();
$count = count($form_data);
for( $i = 0; $i < $count; $i++ )
{
if(!isset($_POST[$form_data[$i]])) {
$out_data[$form_data[$i]] = "NO_DATA";
}
else {
$out_data[$form_data[$i]] = $_POST[$form_data[$i]];
}
}
Now this code technically is working, it is going through the array and assigning values, but it is not doing so properly.
I have hit submit on the form with NOTHING entered. Therefore every item should say "NO_DATA" on my regurgitated output (for user review), however only some items are saying it. All items I have confirmed have name="" and match the array, and have nothing entered in them. Why is "NO_DATA" not being assigned to every item in the array?
Also of note, if I fill in the form completely $out_data is fully and correctly populated. What is the problem with !isset? I've tried doing $_POST[$form_data[$i]] == '' which does put no_data in every instance of no data, however it throws an 'undefined index' warning for every single item on the page whether I write something in the box or not.
Really I just want to know WTF is going on, the dead line for this project is closing fast and EVERY step of the PHP gives me grief.
As far as I can tell by reading around my code is valid, but refuses to execute as advertised.
If you need more code samples please ask.
Really befuddled here, nothing works without an error, help please.
Thanks
-Sean
Instead of checking !isset(), use empty(). If the form posts an empty string, it will still show up in the $_POST as an empty string, and isset() would return TRUE.
I've replaced your incremental for loop with a foreach loop, which is almost always used in PHP for iterating an array.
$out_data = array();
foreach ($form_data as $key) {
if(empty($_POST[$key])) {
$out_data[$key] = "NO_DATA";
}
else {
$out_data[$key] = $_POST[$key];
}
}
PHP's isset returns TRUE unless the variable is undefined or it is NULL. The empty string "" does not cause it to return FALSE. empty() will do exactly what you need, though.
http://php.net/manual/en/function.isset.php
isset() will return FALSE if testing a variable that has been set to
NULL. Also note that a NULL byte ("\0") is not equivalent to the PHP
NULL constant.
Returns TRUE if var exists and has value other than NULL, FALSE
otherwise.

Evaluate a dynamic array key

I have a form that allows the user to add information an their leisure. They can add locations via jQuery in my form so when recieving the data I may have 1 location or 10. Each location has attributes like phone, address, etc. In my form the input names are appended with _1 , _2, etc to show its a new set of data. That is working swimmingly and I just can't seem to find these keys when looping through the $_POST array
private function array_pluck($arr,$text)
{
foreach($arr as $key => $item)
{
if(stripos($key,$text) != 0)
{
$found[] = $item;
}
}
return $found;
}
As I understand it if my array has some keys "office_branch_phone_1, office_branch_phone_2" I should be able to put in "office_branch" in my $text param and it will spit out any keys with the "office_branch" in the name. This isn't working however and I'm a bit stumped.
Since stripos will return the index (and it is a 0-based index returned) != 0 is incorrect.
if (stripos($key,$text) !== false)
Would be the correct way to check it. Give that a shot.
EDIT
Note the use of !== instead of != since 0 tends to be considered false if loosely checked the !== will check the actual type, so 0 is a valid return. Just an extra tidbit of information

Categories