file_get_contents('php:// input')总是返回一个空字符串

时间:2013-10-02 21:17:01

标签: php json rest curl restful-architecture

我正在构建一个PHP RESTful API,遵循this教程。以下函数应该在使用'put'方法时返回随请求一起发送的数据,每次都返回null:

file_get_contents('php://input')

我甚至已经下载并测试了教程中的完整代码示例,它仍然返回null。

我正在使用cURL和以下命令来测试'put'方法:

curl -i -X PUT -d '{"address":"Sunset Boulevard"}' http://localhost/clients/ryan

我已经浪费了几天时间,仍然没有读取json数据。我做错了什么?

13 个答案:

答案 0 :(得分:8)

首先,我能够运行此代码并且运行正常:

--Terminal---------
//I ran this curl request against my own php file:
curl -i -X PUT -d '{"address":"Sunset Boulevard"}' http://localhost/test.php


--PHP--------------
//get the data
$json = file_get_contents("php://input");

//convert the string of data to an array
$data = json_decode($json, true);

//output the array in the response of the curl request
print_r($data);

如果这不起作用,请检查控制台是否有错误和您的php设置:

  1. 您使用的curl网址,请确保该网址确实正常工作且未返回错误。
  2. 打开另一个终端/控制台窗口并运行tail -f /path/to/the/php/log/file,这样你就可以看到这些php调用的输出。
  3. 通常有人会收到此错误:file_get_contents(file://input): failed to open stream: no suitable wrapper could be found可能表示“file:// input”字符串的拼写错误或者在php中禁用allow_url_fopen的事实(如果不确定,请参阅#5)
  4. 确保您的代码是正确的,并且我的意思是确保您没有输入不正确的参数和事物......这些内容不一定会在netbeans中加下划线。
  5. 请记住,file_get_contents仅在PHP设置中将allow_url_fopen设置为true时才有效。这是在php.ini中设置的东西,但你也可以在运行时通过在其他代码之前写下以下代码的内容来更改设置:

    ini_set("allow_url_fopen", true);
    

答案 1 :(得分:8)

noted elsewhere on the web一样,如果重定向了请求,则php://input的内容将无法通过。也许您的Web服务器具有从以www开头的URL到没有www的URL的重定向,或从使用HTTP的URL到使用HTTPS的URL的重定向。检查您的Web服务器日志以验证这一点,并采取相应措施避免在调用Web服务时进行重定向。

答案 2 :(得分:2)

我用这段代码编写了一个头文件:

if($_SERVER["REQUEST_METHOD"] == "POST" && $_SERVER["CONTENT_TYPE"] == "application/json")
{
  $data = file_get_contents("php://input", false, stream_context_get_default(), 0, $_SERVER["CONTENT_LENGTH"]);
  global $_POST_JSON;
  $_POST_JSON = json_decode($_REQUEST["JSON_RAW"],true);

  // merge JSON-Content to $_REQUEST 
  if(is_array($_POST_JSON)) $_REQUEST   = $_POST_JSON+$_REQUEST;
}

它检查正确的内容类型,并且只读取尽可能多的后输入,如Content-Length标头中指定的那样。 当收到有效的JSON时,它创建了一个全局数组$ _POST_JSON。

因此,您可以像使用网址编码的POST值一样使用您的JSON内容。

示例:

 echo $_POST_JSON["address"];
 // or
 echo $_REQUEST["address"];

答案 3 :(得分:2)

我也遇到了这个错误,我的解决方案是将数据格式更改为raw。

我从php doc得到它

:php://input is not available with enctype="multipart/form-data".

答案 4 :(得分:1)

正确的函数调用是:

file_get_contents("php://input");

您应该收到一条错误消息,指出php:input不存在...

在任何情况下,PUT用于将文件上传到服务器,假设服务器支持它。通常,您会使用POST一个适合内容的Content-Type标题。

答案 5 :(得分:1)

在Windows上,'单一和#34;双"的组合引号n#39;似乎不起作用。在json数据中使用escape作为引号(如下所示)&它应该工作

curl -X PUT -d "{\"address\":\"Sunset Boulevard\"}" http://localhost/clients/ryan

答案 6 :(得分:0)

我明白了,

您需要在请求网址的末尾添加filename.php,或者需要重写.htaccess文件中的服务器规则来解决此问题。

curl -i -X PUT -d '{"address":"Sunset Boulevard"}' http://localhost/clients/ryan/{filename.php}

用适当的文件名替换{filename.php}。 :)

答案 7 :(得分:0)

我有同样的问题。 最终,我发现问题出在客户端,我没有对json对象进行字符串化处理(以前我使用的是nodejs服务器,而且还可以)。 完成此操作后,我便以常规参数的形式在$ _POST(不是json)中接收了数据。

答案 8 :(得分:0)

根据需要进行编辑

function getPostObject() {
    $str = file_get_contents('php://input');
    $std = json_decode($str);
    if ($std === null) {
        $std = new stdClass();
        $array = explode('&', $str);
        foreach ($array as $parm) {
            $parts = explode('=', $parm);
            if(sizeof($parts) != 2){
                continue;
            }
            $key = $parts[0];
            $value = $parts[1];
            if ($key === NULL) {
                continue;
            }
            if (is_string($key)) {
                $key = urldecode($key);
            } else {
                continue;
            }
            if (is_bool($value)) {
                $value = boolval($value);
            } else if (is_numeric($value)) {
                $value += 0;
            } else if (is_string($value)) {
                if (empty($value)) {
                    $value = null;
                } else {
                    $lower = strtolower($value);
                    if ($lower === 'true') {
                        $value = true;
                    } else if ($lower === 'false') {
                        $value = false;
                    } else if ($lower === 'null') {
                        $value = null;
                    } else {
                        $value = urldecode($value);
                    }
                }
            } else if (is_array($value)) {
                // value is an array
            } else if (is_object($value)) {
                // value is an object
            }
            $std->$key = $value;
        }
        // length of post array
        //$std->length = sizeof($array);
    }
    return $std;
}

答案 9 :(得分:0)

确保没有正在进行的重定向(例如httphttp://.php/

file_get_contents(php://input)不会通过重定向传递正文内容(尽管我认为可以配置Web服务器来实现)。

一种检查重定向的快速方法是使用curl检查URL。在命令行上: curl -IL http://example.com/api

答案 10 :(得分:0)

对我来说,这个问题突然开始了。
我已经安装了ssl证书。
当我查看响应代码时显示301,然后我意识到并更改了
http://

http s ://
,使用file_get_contents('php:// input')获得了所有请求。

在您的示例curl调用中:
将s放在http之后,如下所示:
curl -i -X PUT -d '{"address":"Sunset Boulevard"}' https://localhost/clients/ryan

答案 11 :(得分:0)

{
  "action":"get_events_by_category",
  "category_id":2
}

您的行字符串数据必须为双引号“”不能使用单引号“

答案 12 :(得分:0)

FWIW 我使用 Postman 发送值。在正文选项卡上,我应该使用“原始”选项卡发送 json {"ID":1234,"Type":"Blah"} 但我愚蠢地使用表单数据选项卡放入键/值使 php://input 结果为 NULL。一旦我切换到使用带有 JSON 的原始选项卡,那么一切都按预期工作。