PHP 一些 $_POST 值缺失但存在于 php://input 中
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5077969/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
PHP some $_POST values missing but are present in php://input
提问by jankes
I have a very big html form (containing table with rows, which contain multiple inputs), which i need to submit to PHP script via POST request. The problem is some values don't come through and are absent in PHP's $_POST superglobal.
我有一个非常大的 html 表单(包含带有行的表,其中包含多个输入),我需要通过 POST 请求将其提交给 PHP 脚本。问题是某些值没有通过,并且在 PHP 的 $_POST 超全局变量中不存在。
I checked (using Firebug extension) that the values are actually sent to server by the browser.
我检查(使用 Firebug 扩展)这些值实际上是由浏览器发送到服务器的。
$_POST gets populated, but some values are just missing.
$_POST 被填充,但只是缺少一些值。
I checked what is raw request using:
我使用以下方法检查了什么是原始请求:
$raw_post = file_get_contents('php://input');
and the string returned has the values. They are just not parsed into $_POST array. The strange thing i noticed is, it seems that the php://input values are cut after some length, and rest of the string does not come through to $_POST.
并且返回的字符串具有值。它们只是没有被解析为 $_POST 数组。我注意到的奇怪的事情是,似乎 php://input 值在某个长度后被截断了,并且字符串的其余部分没有通过 $_POST。
I thought about post_max_size and memory_limit and set them to large values:
我考虑了 post_max_size 和 memory_limit 并将它们设置为大值:
memory_limit = 256M
post_max_size = 150M
但根据 php 文档,如果请求大于 post_max_size,$_POST 不应包含任何值。Due to big size of form and request I cannot post it here, but i can post php script i used to debug the problem:
由于表单和请求很大,我不能在这里发布它,但我可以发布我用来调试问题的 php 脚本:
var_dump($file = file_get_contents('php://input'));
var_dump($_POST);
//... then i parsed the $file
Server version: Apache/2.2.9 (Debian)
PHP version: PHP 5.3.2-0.dotdeb.2
服务器版本:Apache/2.2.9 (Debian)
PHP 版本:PHP 5.3.2-0.dotdeb.2
Can enyone explain reason of such strange PHP behaviour, and what should i do (change php settings, code?) to use $_POST array while processing form?
任何人都可以解释这种奇怪的 PHP 行为的原因,我应该怎么做(更改 php 设置、代码?)在处理表单时使用 $_POST 数组?
EDIT: To be clear: not only the values are missing. $_POST does not contain these keys either.
编辑:要清楚:不仅缺少值。$_POST 也不包含这些键。
e.x. fragment of raw post:
原始帖子的前片段:
t_dodparam%5B198%5D=&t_dodparam2%5B198%5D=&t_kolejnosc%5B198%5D=199&n_indeks=201&n_wartosc=testtesttest
Key 't_dodparam' is in post and it has key 198. The rest of parameters are missing (e.x. t_dodparam2 is in post, but it has no such key as 198, and there is no such key as n_wartosc in $_POST)
键 't_dodparam' 在 post 中,它有键 198。其余参数丢失(ex t_dodparam2 在 post 中,但它没有 198 这样的键,并且 $_POST 中没有 n_wartosc 这样的键)
采纳答案by felixsigl
PHP modifies fields containing the characters space, dot, open square bracket and others to be compatible with with the deprecated register_globals
PHP 修改包含空格、点、左方括号等字符的字段以与已弃用的 register_globals 兼容
you can find a lot of workarounds in the comments here: PHP: Variables From External Sources
您可以在此处的评论中找到很多解决方法: PHP:来自外部源的变量
For Exampe (comment by POSTer):
例如(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;
}
?>
回答by Juanita
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.
我只是通过在我的 PHP 配置文件中向 max_input_vars 添加一个值来解决这个问题。根据此。它是在 5.3.9 中引入的,但经过一些软件包升级后,我在 5.3.2 中遇到了这个问题。
The default for max_input_vars is 1000, which was too small for my form.
max_input_vars 的默认值是 1000,这对我的表单来说太小了。
回答by Dalin
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.
导致这种情况的原因有很多。最好检查您的错误日志。导致此症状的许多事情会将消息放入错误日志中,但不会在您的 PHP 应用程序中显示错误。
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
Suhosin 是 PHP 的扩展,旨在保护服务器和用户免受 PHP 应用程序和 PHP 核心中已知和未知缺陷的影响。它所做的一件事是限制 $_POST、$_GET、$_REQUEST 和 $_COOKIE 的大小。如果您的问题是 Suhosin,您的日志中会出现错误,例如
ALERT - configured POST variable limit exceeded - dropped variable 'foo'
警报 - 超出配置的 POST 变量限制 - 丢弃变量“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:
解决方法很简单,只需要增加php.ini中允许的最大变量数即可。如果您没有 suhosin 部分,只需创建一个。像这样:
[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.
还有其他 suhosin 设置可能会导致这种情况,但这些是最有可能的候选者。
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 有一个名为 register_globals(现已弃用)的设置,它可以自动将 GET 和 POST 变量转换为 PHP 变量。因此,如果您的表单具有字段 'foo' 和 'bar',则在提交该表单时,将自动创建变量 $foo 和 $bar。但是,有几个字符不能用于 PHP 变量名(空格、点、左方括号等)。根据您使用的字符,变量可能会去除无效字符、丢失其值或未设置。尽管不再使用 register_globals,但 PHP 在构建 $_POST、$_GET、$_REQUEST 和 $_COOKIE 时仍会去除这些字符。如果您无法修复表单字段的值,您可以尝试以下操作:
<?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;
}
?>
回答by xavividal
What about using "parse_str"to convert the query string into php structures? This funcion is the inverse of http_build_query.
使用“parse_str”将查询字符串转换为php结构怎么样?这个函数是 http_build_query 的逆函数。
$b = array();
parse_str(file_get_contents("php://input"), $b);
回答by Jeremy Harris
I found this answer via a search and feel I should offer an alternative issue. In my case, my post wasn't too large, and yet the value I was submitting in the field was not showing up in the $_POST array. As it turned out, I accidentally had another field further down in my form with the same name. So:
我通过搜索找到了这个答案,并觉得我应该提供一个替代问题。就我而言,我的帖子不是太大,但我在该字段中提交的值并未显示在 $_POST 数组中。事实证明,我不小心在表单的下方有另一个同名字段。所以:
<form>
<input type="text" name="field1">
<input type="text" name="field2">
<input type="text" name="field3">
<input type="text" name="field1">
<input type="submit">
</form>
When the $_POST
variable is populate with data from that form, the value in your first field will be overwritten with the value in that last field with the same name. If the first field is required and you fill in a value, but the last field is not required and gets submitted empty, you will see similar symptoms as this question because the value $_POST['field1'] will show the value of the last element in you form which is empty.
当$_POST
使用该表单中的数据填充变量时,第一个字段中的值将被最后一个同名字段中的值覆盖。如果第一个字段是必填字段并且您填写了一个值,但最后一个字段不是必需的并且提交为空,您将看到与此问题类似的症状,因为值 $_POST['field1'] 将显示最后一个字段的值你表单中的元素是空的。
TLDR:
域名注册地址:
Make sure to check for duplicate field names in your form!
确保检查表单中的重复字段名称!
回答by torillt
For future reference: On an Ubuntu box, I've been struggling with this issue since a relatively long time and used to adopt a workaround similar as described above to save the day. I now tracked the issue down in my php.ini and finally found it in line with max_input_nesting_level = 0I commented the line above, restarted apache and all's fixed.
供将来参考:在 Ubuntu 机器上,我一直在努力解决这个问题,因为相对较长时间,并且过去常常采用与上述类似的解决方法来挽救这一天。我现在在我的 php.ini 中跟踪了这个问题,最后发现它符合 max_input_nesting_level = 0我评论了上面的行,重新启动了 apache 并且一切都已修复。
回答by Ian
I am posting Jquery's .ajax() function. I was trying to retrieve my data from $_POST
but it was incomplete. Then I found this post which put me on the right track. However, the getRealPOST() method described above wasn't working for me - it can't handle multi-dimentional and nested arrays very well. Instead I used PHP's parse_str()
method which did the trick and was a bit cleaner:
我正在发布 Jquery 的 .ajax() 函数。我试图从中检索我的数据,$_POST
但它不完整。然后我找到了这篇文章,它让我走上了正轨。但是,上面描述的 getRealPOST() 方法对我不起作用 - 它不能很好地处理多维和嵌套数组。相反,我使用了 PHP 的parse_str()
方法,该方法可以解决问题并且更简洁:
$rawdata = file_get_contents('php://input');
$urldecoded = urldecode($rawdata);
parse_str($urldecoded, $parsed);
$data = $parsed['data'];
(In my JS I'm posting an object where the payload is in the data
property. Yours would be likely be different.)
(在我的 JS 中,我发布了一个对象,其中有效载荷位于data
属性中。你的可能会有所不同。)
I also went into my php.ini and cranked up max_memory
and max_input_vars
, but it didn't seem to solve my issue. I also spent a while chasing a red herring because I was using my error log to print the raw data, and I forgot that error_log
has a limit on how many characters it will print unless you remember to increase it.
我也进入了我的 php.ini 并启动了max_memory
和max_input_vars
,但它似乎没有解决我的问题。我还花了一段时间来追赶红鲱鱼,因为我正在使用我的错误日志来打印原始数据,而且我忘记了error_log
它会打印多少字符的限制,除非您记得增加它。
Anyway, hope this helps to anyone who finds themselves battling this issue.
无论如何,希望这对发现自己与此问题作斗争的任何人都有帮助。
回答by mosherjm
I had this same issue and it turned out that I was using AJAX to dynamically modify the input field based on other inputs in the form. The ajax function re-created the input and failed to include an input name.
我遇到了同样的问题,结果我使用 AJAX 根据表单中的其他输入动态修改输入字段。ajax 函数重新创建了输入,但未能包含输入名称。
回答by Rycochet
Came across this (admittedly old) post while trying to find a fix for the bug of Javascript Object keys including square brackets in their names and then PHP getting confused and acting like it's never even heard of nesting. @Dalin has a good basic response, but it doesn't make a nested array, nor does it convert value types to boolean / number - hence my version (get_real_post()is also on GitHub).
在试图找到解决 Javascript 对象键的错误(包括其名称中的方括号)时遇到了这个(不可否认的旧)帖子,然后 PHP 变得困惑并表现得好像它甚至从未听说过嵌套。@Dalin 有一个很好的基本响应,但它不会创建嵌套数组,也不会将值类型转换为布尔值/数字 - 因此我的版本(get_real_post()也在 GitHub 上)。
Despite the name, this should work identically for _GET (ie, anything that php://input
grabs).
尽管名称如此,但这对于 _GET(即任何php://input
抓取的东西)应该同样有效。
/**
* 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;
}
回答by Nairit Kumar Singha Deo
I faced the same problem. My form was creating the input elements in a loop. Upto 1000 input elements were getting posted and print_r($_POST);
showed all the posted values.
我遇到了同样的问题。我的表单正在循环中创建输入元素。多达 1000 个输入元素被发布并print_r($_POST);
显示所有发布的值。
When the input elements in the form numbered above 1000, print_r($_POST)
just vanished. As if the form was not getting posted at all. I reached your page of stackoverflow.comby google search.
当表单中的输入元素编号超过 1000 时,print_r($_POST)
就消失了。好像表格根本没有发布一样。我通过谷歌搜索到达了你的stackoverflow.com页面。
Yes increasing post_max_size
, memory_limit
etc did not solve anything. I have practical experience that increasing memory_limit
beyond 128M
can be dangerous too. Once our live Apache hosting server got hung up. I was the experimenter :-)
是的增加post_max_size
,memory_limit
等没有解决任何问题。我的实践经验表明,memory_limit
超越128M
也可能是危险的。一旦我们的实时 Apache 托管服务器挂断了。我是实验者:-)
max_input_vars
was the only limiting factor.
max_input_vars
是唯一的限制因素。
echo ini_get('max_input_vars');
showed that it was 1000 by default.
Strangely max_input_vars
was absent in the php.ini.
Anyway I added
显示默认为1000。奇怪的max_input_vars
是php.ini 中没有。反正我加了
max_input_vars=10000
in my php.iniand restarted Apache.
在我的php.ini 中并重新启动 Apache。
Now echo ini_get('max_input_vars');
showed that it had increased to 10000
and my large form data could be trapped after posting. Problem solved.
现在echo ini_get('max_input_vars');
显示它已经增加到10000
并且我的大表格数据在发布后可能会被困。问题解决了。
I see that the max_input_vars is PHP_INI_PERDIR type. Which means I cannot change its value for the individual php page where I need a higher value using ini_set('max_input_vars', 10000);
我看到 max_input_vars 是 PHP_INI_PERDIR 类型。这意味着我无法使用 ini_set('max_input_vars', 10000); 更改需要更高值的单个 php 页面的值。