PHP的一些$ _POST值丢失,但存在于PHP:/ /input
我有一个非常大的HTML表单(包含行,其中包含多个input表),我需要通过POST请求提交给PHP脚本。 问题是有些值没有通过,并没有在PHP的$ _POST超全球缺席。
我检查(使用Firebug的扩展),实际上是由浏览器发送到服务器的值。
$ _POST被填充,但有些值只是丢失。
我检查了什么是原始请求使用:
$raw_post = file_get_contents('php://input');
并返回的string具有值。 他们只是不被parsing成$ _POST数组。 我注意到的奇怪的事情是,似乎php://input值被剪切了一段时间后,其余的string不会通过$ _POST。
我想过post_max_size和memory_limit并将它们设置为较大的值:
memory_limit = 256M post_max_size = 150M
但根据PHP文档$ _POST不应包含任何值,如果请求比post_max_size大。
由于forms和请求的大尺寸我不能发布在这里,但我可以发布php脚本我用来debugging问题:
var_dump($file = file_get_contents('php://input')); var_dump($_POST); //... then i parsed the $file
服务器版本:Apache / 2.2.9(Debian)
PHP版本:PHP 5.3.2-0.dotdeb.2
可以enyone解释这种奇怪的PHP行为的原因,我应该怎么做(更改PHP设置,代码?)使用$ _POST数组,同时处理表单?
编辑:要清楚:不仅值的缺失。 $ _POST也不包含这些键。
原始文章的片段:
t_dodparam%5B198%5D=&t_dodparam2%5B198%5D=&t_kolejnosc%5B198%5D=199&n_indeks=201&n_wartosc=testtesttest
密钥“t_dodparam”在后,它有键198.其余的参数是丢失的(例如t_dodparam2在后,但没有这样的密钥198,并没有这样的关键像$ _POST中的n_wartosc)
PHP修改包含字符空间,点,方括号和其他字符的字段以与已弃用的register_globals兼容
您可以在这里的注释中find很多解决方法: PHP:来自外部源的variables
对于Exampe(由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; } ?>
我只是通过在我的PHPconfiguration文件中为max_input_vars添加一个值来解决这个问题。 据此。 它是在5.3.9中引入的,但在一些软件包升级之后,我遇到了5.3.2中的问题。
max_input_vars的默认值是1000,这对于我的表单来说太小了。
有很多不同的事情可能导致这一点。 最好查看你的错误日志。 导致此症状的许多事件都会将消息放入错误日志中,但不会在PHP应用程序中显示错误。
一些可能的原因:
了Suhosin
Suhosin是PHP的扩展,旨在保护服务器和用户免受PHP应用程序和PHP核心中已知和未知的缺陷。 其中一件事是限制$ _POST,$ _GET,$ _REQUEST和$ _COOKIE的大小。 如果你的问题是Suhosin,你会在你的日志中出现错误,如
ALERT – 已超出configuration的POSTvariables限制 – 已丢弃variables'foo'
解决方法很简单,只需增加php.ini中允许的variables的最大数量即可。 如果你没有suhosin部分,只需创build一个。 像这样:
[suhosin] suhosin.request.max_vars = 1000 # Default is 200 suhosin.post.max_vars = 1000 # Default is 200
还有其他的suhosin设置可能导致这种情况,但这些是最有可能的候选人。
无效的表单字段名称
过去,PHP有一个名为register_globals的设置(现在是depricated),它自动将GET和POSTvariables转换成PHPvariables。 所以如果你的表单有字段'foo'和'bar',当表单被提交时,variables$ foo和$ bar会被自动创build。 但是有几个字符在PHPvariables名称(空格,点,方括号等)中无效。 根据您使用的字符,variables可能会有无效的字符被剥离,缺less其值,或未设置。 尽piperegister_globals已不再使用,但PHP在构build$ _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; } ?>
那么使用“parse_str”将查询string转换为php结构呢? 这个函数是http_build_query的反函数。
$b = array(); parse_str(file_get_contents("php://input"), $b);
以供将来参考:在一个Ubuntu的盒子,我一直在努力解决这个问题,因为相对较长的时间,并采用类似于上述的解决方法来节省一天的时间。 我现在跟踪了我的php.ini中的问题,最后发现它符合max_input_nesting_level = 0我评论上面的行,重新启动Apache和所有的固定。
我发布Jquery的.ajax()函数。 我试图从$_POST
检索我的数据,但它是不完整的。 然后我发现这个post让我走上正轨。 但是,上面描述的getRealPOST()方法不适用于我,它不能很好地处理多维和嵌套数组。 相反,我使用了PHP的parse_str()
方法,这个方法做parse_str()
,
$rawdata = file_get_contents('php://input'); $urldecoded = urldecode($rawdata); parse_str($urldecoded, $parsed); $data = $parsed['data'];
(在我的JS我发布一个对象的有效载荷是在data
属性,你的可能会有所不同。
我也进入了我的php.ini,并启动了max_memory
和max_input_vars
,但似乎没有解决我的问题。 我也花了一段时间追逐一个红鲱鱼,因为我正在使用我的错误日志来打印原始数据,我忘记了error_log
限制了它将打印多less字符,除非你记得增加它。
无论如何,希望这有助于任何发现自己在与这个问题作斗争的人。
我有这个相同的问题,事实certificate,我正在使用AJAXdynamic修改input字段的基础上的其他input的forms。 ajax函数重新创build了input,但未包含input名称。
遇到这个(诚然是旧的)的post,同时试图findJavascript对象键包括方括号在他们的名字的错误修复,然后PHP变得困惑和performance就像从来没有听说过的嵌套。 @Dalin有一个很好的基本的响应,但它不会产生一个嵌套数组,也不会将值types转换为布尔值/数字 – 因此我的版本( get_real_post()也在GitHub上)。
尽pipe有这个名字,但是这对于_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; }
我通过searchfind了这个答案,觉得我应该提供一个替代的问题。 在我的情况下,我的post不是太大,但是我在字段中提交的值没有显示在$ _POST数组中。 事实certificate,我意外地在同一个名字的forms下又进了一个场。 所以:
<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>
当$_POST
variables填充来自该表单的数据时,第一个字段中的值将被相同名称的最后一个字段中的值覆盖。 如果第一个字段是必需的,并且您填写了一个值,但是最后一个字段不是必需的并且被提交为空,您将看到与此问题相似的症状,因为值$ _POST ['field1']将显示最后一个值元素在你的forms是空的。
TLDR:
请务必在表单中检查重复的字段名称!
我面临同样的问题,我发现一个非常有价值的解决scheme,而不会增加.ini中的任何限制或大小。 我们知道,max_input_vars = 1000默认情况下,这是完美的。 只要做一件事连接数组值,并尝试精确你的variables数在1000以下。每个variables名称计数一个不是它们的值。 例如:
<code> $i = 10; //counts 1 $i = array(1,2,3,4,5); //counts 5 </code>
你可以这样做:
<code> $i = 1_2_3_4_5; // counts 1 </code>
希望了解。
用$ _POST使用htmlspecialchars
。 例如:
$day1=htmlspecialchars($_POST["day"]);
我希望这会起作用。