PHP некоторые значения $ _POST отсутствуют, но присутствуют в php: // input

У меня очень большая форма html (содержащая таблицу со строками, содержащую несколько входов), которые мне нужно отправить на PHP-скрипт через запрос POST. Проблема в том, что некоторые значения не проходят и отсутствуют в суперглобальном PHP $ _POST.

Я проверил (используя расширение Firebug), что значения фактически отправляются на сервер браузером.

$ _POST заселяется, но некоторые значения просто отсутствуют.

Я проверил, что является сырым запросом, используя:

$raw_post = file_get_contents('php://input'); 

и возвращаемая строка имеет значения. Они просто не анализируются в массив $ _POST. Странная вещь, которую я заметил, кажется, что значения ввода php: // сокращаются после некоторой длины, а остаток строки не доходит до $ _POST.

Я подумал о post_max_size и memory_limit и установил их в большие значения:

 memory_limit = 256M post_max_size = 150M 

но согласно документации php $ _POST не должен содержать никаких значений, если запрос сделан больше, чем post_max_size.

Из-за большого размера формы и запроса я не могу опубликовать ее здесь, но я могу опубликовать скрипт php, который я использовал для отладки проблемы:

 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 при обработке формы?

EDIT: чтобы быть ясным: не только значения отсутствуют. $ _POST также не содержит этих ключей.

ex фрагмент исходного сообщения:

 t_dodparam%5B198%5D=&t_dodparam2%5B198%5D=&t_kolejnosc%5B198%5D=199&n_indeks=201&n_wartosc=testtesttest 

Ключ «t_dodparam» находится в столбце и имеет ключ 198. Остальные параметры отсутствуют (ex t_dodparam2 находится в сообщении, но у него нет такого ключа, как 198, и нет такого ключа, как n_wartosc в $ _POST)

PHP изменяет поля, содержащие пространство символов, точку, открытую квадратную скобку и другие, совместимые с устаревшими register_globals

вы можете найти много обходных путей в комментариях здесь: PHP: переменные из внешних источников

Для 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; } ?> 

Я просто исправил эту проблему, добавив значение в max_input_vars в свой файл конфигурации PHP. В соответствии с этим . он был введен в 5.3.9, но после некоторых обновлений пакетов я столкнулся с проблемой в 5.3.2.

Значение по умолчанию для max_input_vars равно 1000, что слишком мало для моей формы.

Это может вызвать много разных причин. Лучше всего проверить журнал ошибок. Многие из вещей, которые вызывают этот симптом, помещают сообщения в журнал ошибок, но не отображают ошибки в вашем приложении PHP.

Некоторые из возможных причин:

Suhosin

Suhosin – это расширение для PHP, предназначенное для защиты серверов и пользователей от известных и неизвестных недостатков в PHP-приложениях и ядре PHP. Одной из вещей, которые он делает, является ограничение размера $ _POST, $ _GET, $ _REQUEST и $ _COOKIE. Если ваша проблема – Suhosin, вы получите сообщение об ошибке в своем журнале, например

ALERT – превышен предел переменной POST – сброшенная переменная 'foo'

Решение простое, просто увеличьте максимальное количество разрешенных переменных в php.ini. Если у вас нет секции сухозина, просто создайте ее. Например:

 [suhosin] suhosin.request.max_vars = 1000 # Default is 200 suhosin.post.max_vars = 1000 # Default is 200 

Есть другие настройки сухозина, которые могут вызвать это, но это наиболее вероятные кандидаты.

Неверные имена полей формы

Еще в старые времена 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; } ?> 

Как насчет использования «parse_str» для преобразования строки запроса в php-структуры? Эта функция является инверсной для http_build_query.

  $b = array(); parse_str(file_get_contents("php://input"), $b); 

Для справок в будущем: в ящике Ubuntu я довольно долгое время пытался справиться с этой проблемой и использовал метод обхода, аналогичный описанному выше, чтобы сохранить день. Я теперь отслеживал проблему в своем php.ini и, наконец, нашел ее в соответствии с max_input_nesting_level = 0 Я прокомментировал вышеприведенную строку, перезапустил apache и все исправлено.

Я отправляю функцию .ajax () JQuery. Я пытался извлечь мои данные из $_POST но он был неполным. Затем я нашел этот пост, который поставил меня на правильный путь. Однако метод getRealPOST (), описанный выше, не работал для меня – он не может обрабатывать многомерные и вложенные массивы очень хорошо. Вместо этого я использовал метод parse_str() PHP, который сделал трюк и был немного чище:

 $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 имеет ограничение на количество символов, которые он будет печатать, если вы не забудете его увеличить.

В любом случае, надеюсь, что это поможет любому, кто сталкивается с этой проблемой.

У меня была эта же проблема, и оказалось, что я использовал AJAX для динамического изменения поля ввода на основе других входных данных в форме. Функция ajax повторно создала вход и не включила имя ввода.

Прошел через это (по общему признанию, старое) сообщение, пытаясь найти исправление для ошибки ключей Javascript Object, включая квадратные скобки в их именах, а затем PHP запутался и действовал так, как будто он даже не слышал о гнездовании. @Dalin имеет хороший базовый ответ, но он не создает вложенный массив и не преобразует типы значений в boolean / number – поэтому моя версия ( get_real_post () также находится в GitHub).

Несмотря на название, это должно работать одинаково для _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; } 

Я нашел этот ответ через поиск и почувствовал, что должен предложить альтернативный вопрос. В моем случае мой пост был не слишком большим, и все же значение, которое я подавал в поле, не отображалось в массиве $ _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> 

Когда переменная $_POST заполняется данными из этой формы, значение в вашем первом поле будет перезаписано значением в этом последнем поле с тем же именем. Если требуется первое поле, и вы заполните значение, но последнее поле не требуется и будет отправлено пустым, вы увидите похожие симптомы, как этот вопрос, потому что значение $ _POST ['field1'] покажет значение последнего элемент в форме, пустой.

TLDR:

Обязательно проверьте наличие дубликатов полей в вашей форме!

Я столкнулся с такой же проблемой, и я нашел очень ценное решение без увеличения каких-либо ограничений или размеров в .ini. Мы знаем, что max_input_vars = 1000 по умолчанию, и это префект. Просто сделайте одну вещь, чтобы объединить значения массива и попытаться точно определить количество переменных в 1000. Каждое имя переменной считается одним из них, а не их значениями. Например:

 <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> 

Надеюсь на понимание.

Используйте htmlspecialchars с вашим $ _POST. Например:

 $day1=htmlspecialchars($_POST["day"]); 

Надеюсь, это сработает.