PHP Foreach() invalid argument - php

I'm receiving the fooling error below but not sure why. the $_Post all have data.
error: Warning: Invalid argument supplied for foreach() in /home/soc/process_member.php on line 19
$valid = true;
foreach($_POST['add'] && $_POST['cpl'] as $value) {
if(!isset($value)) {
$valid = false;
}
}
if(!$valid) {
$err .= 'please fill in all fields';
$en['reg_error'] = '<div class=err style="color: #FF0000;"><b>'._error.': '.$err.'</b></div><br>';
load_template('modules/members/templates/s_reg.tpl');
}

You should read more about PHP. There are two syntaxes for "foreach":
foreach (array_expression as $value)
statement
foreach (array_expression as $key => $value)
statement
This is totally wrong:
foreach($_POST['add'] && $_POST['cpl'] as $value) {
Let me give you an example:
<?php
foreach (array(1, 2, 3, 4) as &$value) {
$value = $value * 2;
}
?>
For more info, check the official PHP Documentation regarding foreach: http://php.net/manual/en/control-structures.foreach.php

I think what you want is a merged array:
foreach(array_merge($_POST['add'], $_POST['cpl']) as $value) {
// ...

First, in PHP, result of && operation is always boolean (i.e., true or false) - and you cannot supply it into foreach (and why you may wish to?), hence the error.
Second, even if it were possible, it'd still make little sense to use isset here: if either $_POST['add'] or $_POST['cpl'] is indeed unset, the notice is raised.
So, you can either just rewrite the first section of your code like this:
$valid = isset($_POST['add']) && isset($_POST['cpl']);
... or, taking into account the flexible nature of isset construct, just...
$valid = isset($_POST['add'], $_POST['cpl']);
... because, as said in its' official doc:
If multiple parameters are supplied then isset() will return TRUE only
if all of the parameters are set. Evaluation goes from left to right
and stops as soon as an unset variable is encountered.
If there's actually a whole big set of args to check and/or you're too lazy to type '$_POST' each time, use foreach to go through the array of their names (and not the actual values!) instead:
$valid = true;
foreach (array('add', 'cpl', 'whatever', 'it', 'takes') as $argName) {
if (! isset($_POST[$argName])) {
$valid = false;
break;
}
}

Related

Undefined variable: missing in

I'm currently trying to figure out PHP. however I keep running into some errors.
this is my PHP line of code that has two errors:
1)Undefined variable: missing
2)in_array() expects parameter 2 to be array
my best guess would be the missing variable ($missing) would be missing however I defined it just above it.
the errors are in the line: if (!in_array($email, $missing))
foreach ($_POST as $key => $value) {
if (in_array($key, $expected)) {
if (!is_array($value)) {
$value = trim($value);
}
if (empty($value) && in_array($key,$required)) {
$$key = '';
$missing[] = $key;
} else {
$$key = $value;
}
}
}
if (!in_array($email, $missing)) {
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
if (!$email){
$errors['email'] = 'use a valid mail address';
}
}
1)Undefined variable: missing
Yes, you've defined it, but only in one branch of the code. You don't guarantee its existence. There's obviously a situation when your variable isn't defined at all and you need to take care of it before trying to use it somewhere.
2)in_array() expects parameter 2 to be array
As the error says, you need to make 100% sure that your second parameter is indeed an array AND is defined.

How do I suppress this foreach warning when the function that contains it relies on $_POST data

I have the following code which functions as intended when $_POST values are set, however, if no $_POST values(IE when the page is first loaded) are set I get "Warning: Invalid argument supplied for foreach() in..." $_POST is always going to be empty until the user clicks submit. I have tried empty(), isset() and now count().
if(isset($_POST['submitbtn'])){
$errors = CheckFormErrors();
if(count($errors) == 0){
$data = CleanFormData();
print_r($data);
}
}
Here is the function being called(not yet complete, but it is working):
function CleanFormData(){
foreach($_POST as $key => $value){
if($key == 'description'){ continue; }
if($key == 'file'){ continue; }
if($key == 'role'){ continue; }
$_POST[$key] = is_array($key) ? $_POST[$key]: strip_tags($_POST[$key]);
}
return $_POST;
}
I thought that I could surpress the error by putting it in a conditional statement, evidently that is incorrect. A little help?
As already stated in comments, you have to check if the superglobal $_POST is empty before calling the foreach itself (inside the function), not outside the function - this way you don't have to check for !empty($_POST) every time you are calling this function.
function CleanFormData() {
if (!empty($_POST)) {
foreach($_POST as $key => $value) {
// Loops here
}
}
return $_POST;
}

PHP truncates parameter name after squared brackets?

If the parameter name of an URL contains squared brackets (no matter if they are url-encoded or not), any following character is ignored by PHP and is not made available to the script (e.g. via $_GET).
Example request:
...showget.php?xxx%5B1%5Dyyy=42
$_GET:
Array
(
[xxx] => Array
(
[1] => 42
)
)
As you can see, "yyy" didn't made it. ^^
(tested in PHP 5.3.28 & 5.5.10)
Does somebody know if such URLs are even syntactically valid?
Is this behaviour intended and documented (could not find anything) or should it rather be considered as a bug within PHP?
If intended: Can i change the respective behaviour by changing a special setting or so?
Thanks!
This is intended behaviour. As you saw in your example, PHP builds arrays from GET parameters if it can, that is, if it finds square brackets in the variable name. There's a FAQ entry showing how that can sometimes be useful.
In your case, PHP sees xxx[1]yyy=42 as xxx[1]=42 which becomes an array.
As far as I know, PHP's query string parsing can not be changed, but you could use $_SERVER['QUERY_STRING'] and parse that yourself.
[] in query key names is a hint to PHP that you want an array, e.g.
example.com?foo[]=bar&foo[]=baz
produces
$_GET = array(
'foo' => array('bar', 'baz')
);
This notation also lets you specify keys in the url:
example.com?foo[bar]=baz
$_GET = array(
'foo' => array('bar' => 'baz')
);
But once you get into this array notation, you're not permitted to have anything in the keyname AFTER the [] portion:
example.com?foo[bar]baz=qux
$_GET = array(
'foo' => array('bar' => 'qux')
);
Basically it's related to PHP syntax, where somethign like
$foo['bar']baz
would be a syntax error.
Came across this myself earlier too, and wrote a function to handle it from POST data, but it shouldn't take much to get it to use GET data instead. Such a large amount of code simply to account for the fact that PHP doesn't account for nested square brackets ;-)
/**
* Gets the _POST data with correct handling of nested brackets:
* "path[to][data[nested]]=value"
* "path"
* -> "to"
* -> "data[nested]" = value
* #return array
*/
function get_real_post() {
function set_nested_value(&$arr, &$keys, &$value) {
$key = array_shift($keys);
if (count($keys)) {
// Got deeper to go
if (!array_key_exists($key, $arr)) {
// Make sure we can get deeper if we've not hit this key before
$arr[$key] = array();
} elseif (!is_array($arr[$key])) {
// This should never be relevant for well formed input data
throw new Exception("Setting a value and an array with the same key: $key");
}
set_nested_value($arr[$key], $keys, $value);
} elseif (empty($key)) {
// Setting an Array
$arr[] = $value;
} else {
// Setting an Object
$arr[$key] = $value;
}
}
$input = array();
$parts = array();
$pairs = explode("&", file_get_contents("php://input"));
foreach ($pairs as $pair) {
$key_value = explode("=", $pair, 2);
preg_match_all("/([a-zA-Z0-9]*)(?:\[([^\[\]]*(?:(?R)[^\[\]]*)*)\])?/", urldecode($key_value[0]), $parts);
$keys = array($parts[1][0]);
if (!empty($parts[2][0])) {
array_pop($parts[2]); // Remove the blank one on the end
$keys = array_merge($keys, $parts[2]);
}
$value = urldecode($key_value[1]);
if ($value == "true") {
$value = true;
} else if ($value == "false") {
$value = false;
} else if (is_numeric($value)) {
if (strpos($value, ".") !== false) {
$num = floatval($value);
} else {
$num = intval($value);
}
if (strval($num) === $value) {
$value = $num;
}
}
set_nested_value($input, $keys, $value);
}
return $input;
}

PHP Notice: Array to string conversion Error

Been experiencing this error for a little while and can't find any conclusive answers on fixing it. I have tried removing quotes from $key in line 59 but to no avail.
if (!get_magic_quotes_gpc()) {
if (isset($_POST)) {
foreach ($_POST as $key => $value) {
$_POST['$key'] = trim(addslashes($value));
}
}
if (isset($_GET)) {
foreach ($_GET as $key => $value) {
$_GET[$key] = trim(addslashes($value));
}
}
}
LINE 59
$_POST['$key'] = trim(addslashes($value));
Error On Screen
Notice: Array to string conversion in
C:\Inetpub\vhosts\domain.com\httpdocs\library\config.php on
line 59
Check if it is array before you assign it
$_POST[$key] = !is_array($value) ? trim(addslashes($value)) : '';
// ^ Remove the quotes here // ^ Do something
// Instead of
// Using empty
According to PHP.net the function addslashes() takes a String type as parameter. Check what type $value is. If it is an array itself then addslashes() may be throwing the error.
PS:
You should use $_POST[$key] rather than $_POST['$key'] if you want to use the value of $key as the index of the $_POST array.
I think you should use this code $_POST[$key] = $value; instead of using this $_POST['$key'] = trim(addslashes($value));
or make a check if the value is in array or not
Do this:
foreach ($_POST as &$value) {
$value = is_array($value) ?
array_map(function($x) { return trim(addslashes($x)); } :
trim(addslashes($value));
}
However, this could still fail if any of your parameters are multi-dimensional arrays. As mentioned in the comments, the right solution is to use prepared queries with parameters, rather than interpolating strings into SQL.

PHP Array structure

I am trying to generate an MS Excel spread sheet using PHPExcel 1.7.6 . I am having trouble determining the structure of the array expected.
The code that builds up the columns and rows is as follows:
function _headers() {
$i=0;
foreach ($this->data[0] as $field => $value) {
if (!in_array($field,$this->blacklist)) {
$columnName = Inflector::humanize($field);
$this->sheet->setCellValueByColumnAndRow($i++, 4, $columnName);
}
}
$this->sheet->getStyle('A4')->getFont()->setBold(true);
$this->sheet->getStyle('A4')->getFill()->setFillType(PHPExcel_Style_Fill::FILL_SOLID);
$this->sheet->getStyle('A4')->getFill()->getStartColor()->setRGB('969696');
$this->sheet->duplicateStyle( $this->sheet->getStyle('A4'), 'B4:'.$this->sheet->getHighestColumn().'4');
for ($j=1; $j<$i; $j++) {
$this->sheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($j))->setAutoSize(true);
}
}
function _rows() {
$i=5;
foreach ($this->data as $row) {
$j=0;
foreach ($row as $field => $value) {
if(!in_array($field,$this->blacklist)) {
$this->sheet->setCellValueByColumnAndRow($j++,$i, $value);
}
}
$i++;
}
}
I'm currently getting an 'Invalid argument supplied for foreach()' error.
I would appreciate it if somebody can outline the correct array structure required.
As IsisCode said, it sounds like you're looking in the wrong direction by associating the problem with PHPExcel. That error is generally just saying that the first argument supplied to foreach() isn't an array.
I don't see anything indicating that the problem is explicitly with the initial foreach in the _headers() method though. If there's a non array element in $this->data then your _rows() method could produce the error as well.
Given:
$this->data = Array(
Array('foo' => 'bar'),
'baz'
)
That would cause the second foreach in _rows() to fail, as an example. Your error message should be able to point you to which foreach() is failing, but ultimately it sounds like you've got a non-array element in $this->data where you don't expect it. If that can't be helped, then consider verifying you're dealing with an array before calling foreach:
function _rows() {
$i=5;
foreach ($this->data as $row) {
$j=0;
if(!is_array($row)) { continue; } // Ignore non-array elements
foreach ($row as $field => $value) {
if(!in_array($field,$this->blacklist)) {
$this->sheet->setCellValueByColumnAndRow($j++,$i, $value);
}
}
$i++;
}
Verifying the type of a variable before handing it to a type-specific function is never a bad idea and can save a lot of headache in general.

Categories