关于`$HTTP_RAW_POST_DATA`被弃用的警告

128

我切换到 PHP 5.6.0,现在无论哪里都会出现以下警告:

Deprecated: Automatically populating $HTTP_RAW_POST_DATA is deprecated and will
be removed in a future version. To avoid this warning set
'always_populate_raw_post_data' to '-1' in php.ini and use the php://input stream
instead. in Unknown on line 0

Warning: Cannot modify header information - headers already sent in Unknown on line 0

好的,我依赖于一些被弃用的功能。除了 我没有!

  1. 我从未在任何脚本中使用过这个变量。说实话,我甚至不知道它存在。
  2. phpinfo() 显示我的 always_populate_raw_post_data 设置为 0(禁用)。那么是什么原因导致此问题?

我不想通过将这个值设置为 -1 来“避免警告”。这只会隐藏警告,而且我仍然会有过时的配置。我想要从根本上解决问题,并知道为什么 PHP 认为 HTTP_RAW_POST_DATA 的填充已经开启。


同样的问题,但可能有不同的原因/解决方案:https://dev59.com/J18e5IYBdhLWcg3wNIJp - rr-
当在 PHP >= 5.6 上运行 PHP SoapServer 的 handle() 时,这个警告会给我带来麻烦。这个警告将始终在 SOAP 的响应中输出,以便 SoapClient 的 __soapCall() 将获得“SoapFault 异常:[Client] 看起来我们没有 XML 文档”的异常。这很难调试,因为通常不会显示此警告。 - Johnny Wong
13个回答

137
结果表明,我对错误信息的理解是错误的。我认为它选择的用词非常不当。在谷歌上搜索后,我发现有人和我完全一样误解了这个信息-请参见 PHP错误#66763

针对该错误的 Mike 的帮助毫无意义的回复是:"这就是RM想要的方式。" Tyrael 解释说,将其设置为"-1"不仅可以消除警告,而且还能做到正确的事情即完全禁用填充罪犯变量。结果发现设置为0 仍然在某些情况下填充数据。说一个坏设计!引用PHP RFC

更改 always_populate_raw_post_data INI 设置以接受三个值而不是两个。

  • -1:主功能的行为;永远不要填充 $GLOBALS[HTTP_RAW_POST_DATA]
  • 0/off/whatever:向后兼容的行为(如果内容类型未注册或请求方法不是POST,则填充)
  • 1/on/yes/true:向后兼容的行为(始终填充 $GLOBALS[HTTP_RAW_POST_DATA])

所以,将其设置为-1不仅可以避免警告,就像信息中说的那样,而且还可以最终禁用填充此变量,这正是我想要的。


25
这是一个愚蠢的警告,即使您不使用它所警告的功能也会出现。将_always_populate_raw_post_data_设置为-1。 - srcspider
7
我已将其设置为always_populate_raw_post_data = -1。但现在还是会出现警告并破坏JSON响应。 - itsazzad
2
因此,实际上的答案是进入您的 php.ini 文件并设置(或取消注释)always_populate_raw_post_data = -1 - John
但我真的不明白重点在哪里。这正是警告所说的吗?“要避免此警告,请在php.ini中将'always_populate_raw_post_data'设置为'-1',并使用php://input流”。 - Andreas
@Andreas,关键在于它为什么会这样说,即0和-1之间的区别,0显然是“禁用”,而-1则是...“更强的禁用”?→混淆→这个问题(和答案)的原因。 - rr-
显示剩余2条评论

43

我已经有一段时间没有遇到这个错误了。我为任何可能遇到此问题的人提供了答案。

该错误仅意味着您正在发送一个空的POST请求。这种错误通常在未传递参数的HTTP请求中发现。为了避免这个错误,您可以在不更改php.ini的情况下始终向POST添加一个参数。

例如:

$.post(URL_HERE
    ,{addedvar : 'anycontent'}
    ,function(d){
       doAnyHere(d);
    }
    ,'json' //or 'html','text'
);

4
这是我找到的最佳答案!我已经断断续续地处理这个问题一个月了,一直都在错误的方向上寻找。结果发现只是无意中POST请求为空,一旦修复后一切都很好!谢谢你帮我避免了一个可怕的头痛问题! - Craig Howell
这个解决方案太糟糕了。首先,你假设每个人都在使用jQuery,其次,你强制使用POST变量而不是解决实际问题。 - Exit

34

我在NGINX服务器(DigitalOcean)上遇到了同样的问题-我所要做的就是以root身份登录并修改文件/etc/php5/fpm/php.ini

为了找到带有always_populate_raw_post_data的行,我首先运行了grep:

grep -n 'always_populate_raw_post_data' php.ini

那返回了行 704

704:;always_populate_raw_post_data = -1

然后使用vi编辑器打开那一行的php.ini文件:

vi +704 php.ini

删除分号以取消注释并保存文件:wq

最后重新启动服务器,错误就会消失。


3
如果您的 php.ini 中的行被注释掉,那么您可能正在使用开发配置的 php.ini。 - BadHorsie

13
如果您正在使用 WAMP...

您应该在php.ini中添加或取消注释属性always_populate_raw_post_data并将其值设置为-1。在我的情况下,php.ini位于:

C:\wamp64\bin\php\php5.6.25\php.ini

..但如果您仍然收到警告(就像我一样)

您还应该在phpForApache.ini中设置always_populate_raw_post_data = -1

C:\wamp64\bin\php\php5.6.25\phpForApache.ini

如果您找不到此文件,请打开浏览器窗口并转到:

http://localhost/?phpinfo=1

查找Loaded Configuration File键的值。在我的情况下,WAMP使用的php.ini位于:

C:\wamp64\bin\apache\apache2.4.23\bin\php.ini (符号链接到C:\ wamp64 \ bin \ php \ php5.6.25 \ phpForApache.ini)

最后重新启动WAMP(或单击重新启动所有服务)。

6
如果找不到.htaccess文件,请在根目录下创建它并粘贴此行代码。
将此代码放入.htaccess文件中(已经测试可用于API)。
<IfModule mod_php5.c>
    php_value always_populate_raw_post_data -1
</IfModule>

3
请解释,我的主人。 - Zohaib

5
取消注释

always_populate_raw_post_data = -1 

在php.ini文件中(第703行),重新启动APACHE服务可以帮助我摆脱这个消息。
; Always populate the $HTTP_RAW_POST_DATA variable. PHP's default behavior is
; to disable this feature and it will be removed in a future version.
; If post reading is disabled through enable_post_data_reading,
; $HTTP_RAW_POST_DATA is *NOT* populated.
; http://php.net/always-populate-raw-post-data
; always_populate_raw_post_data = -1

4

当我使用html表单(Post方法)发送数据时,我收到了这个错误信息。我所要做的就是将表单中的编码从"text/plain"更改为"application/x-www-form-urlencoded"或"multipart/form-data"。错误信息非常误导。


4

很不幸,这里@EatOng的回答是不正确的。在阅读他的回答后,我为每个AJAX请求添加了一个虚拟变量(即使有些请求已经有了一些字段),只是为了确保错误永远不会出现。

但现在我遇到了同样的PHP错误。我再次确认我发送了一些POST数据(除了虚拟变量还有其他一些字段)。PHP版本5.6.25always_populate_raw_post_data值设置为0

此外,由于我正在发送一个application/json请求,PHP并没有将它们填充到$_POST中,而是我必须使用json_decode()解码原始POST请求体,它可以通过php://input访问。

正如@rr-引用的回答所述:

0/off/whatever: BC行为(如果内容类型未注册请求方法不是POST,则填充)。

因为请求方法肯定是POST,我想PHP没有识别/喜欢我的Content-Type: application/json请求(为什么?)。

选项1:

手动编辑php.ini文件,并将罪魁祸首的变量设置为-1,正如这里的许多答案所建议的那样。

选项2:

这是PHP 5.6的一个错误。升级PHP。

选项3:

就像@user9541305在这里回答的那样,更改AJAX请求的Content-Typeapplication/x-www-form-urlencodedmultipart/form-data将使PHP从POSTed body填充$_POST(因为PHP喜欢/识别这些content-type头!?)。

选项4:最后的办法

好吧,我不想改变AJAX的Content-Type,这会给调试带来很多麻烦。(Chrome DevTools能够很好地查看JSON请求的POST变量。)

我正在为客户开发这个东西,不能要求他们使用最新的PHP,也不能要求他们编辑php.ini文件。作为最后的选择,我将检查它是否设置为0,如果是,就在我的PHP脚本中编辑php.ini文件。当然,我必须要求用户重新启动Apache。真丢人!

这是一个示例代码:

<?php

if(ini_get('always_populate_raw_post_data') != '-1')
{
    // Get the path to php.ini file
    $iniFilePath = php_ini_loaded_file();

    // Get the php.ini file content
    $iniContent = file_get_contents($iniFilePath);

    // Un-comment (if commented) always_populate_raw_post_data line, and set its value to -1
    $iniContent = preg_replace('~^\s*;?\s*always_populate_raw_post_data\s*=\s*.*$~im', 'always_populate_raw_post_data = -1', $iniContent);

    // Write the content back to the php.ini file
    file_put_contents($iniFilePath, $iniContent);

    // Exit the php script here
    // Also, write some response here to notify the user and ask to restart Apache / WAMP / Whatever.
    exit;
}

4

对于那些在按照接受的答案更改php.init后仍然遇到此问题的人。由于当通过POST进行ajax请求时没有任何参数导致错误发生,所以你需要做的就是将发送方法更改为GET

var xhr = $.ajax({
   url:  url,
   type: "GET",
   dataType: "html",
   timeout: 500,
});

如果出于某种原因您想保留方法POST,则仍有另一种选择是在ajax请求中添加一个空的JSON对象。

var xhr = $.ajax({
   url:  url,
   type: "POST",
   data: {name:'emtpy_petition_data', value: 'empty'}
   dataType: "html",
   timeout: 500,
});

1
注意:如果您正在使用PHPSTORM 在此输入图片描述
我花了一个小时来解决这个问题,一直以为是我的php服务器的问题,所以我在php.ini中将'always_populate_raw_post_data'设置为'-1',但仍然没有用。
直到我发现使用phpStorm内置服务器才是问题的原因,详细信息可以参考这里的答案:LazyOne的答案,所以我想分享一下。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接