PHP some $_POST values missing but are present in php://input
There are many different things that could be causing this. Best to check your error log. Many of the things that cause this symptom will put messages in the error log, but not display errors in your PHP application.
Some of the possible causes:
Suhosin
Suhosin is an extension for PHP designed to protect servers and users from known and unknown flaws in PHP applications and the PHP core. One of the things that it does is limit the size of $_POST, $_GET, $_REQUEST, and $_COOKIE. If your problem is Suhosin you will get an error in your log such as
ALERT - configured POST variable limit exceeded - dropped variable 'foo'
The solution is simple, just increase the maximum number of allowed variables in php.ini. If you don’t have a suhosin section, just create one. Like such:
[suhosin]
suhosin.request.max_vars = 1000 # Default is 200
suhosin.post.max_vars = 1000 # Default is 200
There are other suhosin settings that can cause this, but these are the most likely candidates.
Invalid form field names
Back in the old days PHP had a setting called register_globals (now depricated) that automatically converted GET and POST variables into PHP variables. So if your form had fields 'foo' and 'bar', when that form is submitted the variables $foo and $bar would be automatically created. However there are several characters that are not valid for use in PHP variable names (space, dot, open square bracket and others). Depending on what characters you used, the variable may have the invalid characters stripped, be missing its value, or be unset. Despite the fact that register_globals is no longer used, PHP still strips these characters when building $_POST, $_GET, $_REQUEST, and $_COOKIE. If you are unable to fix the values of the form fields you might try something like:
<?php
/**
* Converts raw POST data into an array.
*
* Does not work for hierarchical POST data.
*
* @return array
*/
function real_post() {
static $post;
if (!isset($post)) {
$pairs = explode("&", file_get_contents("php://input"));
$post = array();
foreach ($pairs as $pair) {
$x = explode("=", $pair);
$post[rawurldecode($x[0])] = rawurldecode($x[1]);
}
}
return $post;
}
?>
PHP modifies fields containing the characters space, dot, open square bracket and others to be compatible with with the deprecated register_globals
you can find a lot of workarounds in the comments here: PHP: Variables From External Sources
For Exampe (comment by POSTer):
<?php
//Function to fix up PHP's messing up POST input containing dots, etc.
function getRealPOST() {
$pairs = explode("&", file_get_contents("php://input"));
$vars = array();
foreach ($pairs as $pair) {
$nv = explode("=", $pair);
$name = urldecode($nv[0]);
$value = urldecode($nv[1]);
$vars[$name] = $value;
}
return $vars;
}
?>
I just fixed this issue by adding a value to max_input_vars in my PHP configuration file. According to this. it was introduced in 5.3.9, yet after some package upgrades I experienced the issue in 5.3.2.
The default for max_input_vars is 1000, which was too small for my form.
What about using "parse_str" to convert the query string into php structures? This funcion is the inverse of http_build_query.
$b = array();
parse_str(file_get_contents("php://input"), $b);