我提交POST到一个php页面如下:

{a:1}

这是请求的主体(POST请求)。 在php中,我需要做什么来提取这个值?

var_dump($_POST); 

不是解决办法,行不通。


要访问POST或PUT请求(或任何其他HTTP方法)的实体体:

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

另外,STDIN常量是php://input的一个已经打开的流,所以你可以选择:

$entityBody = stream_get_contents(STDIN);

从PHP手册的I/O streamsdocs条目:

input是一个只读流,允许你读取原始数据 来自请求体。在POST请求的情况下,更可取 使用php://input而不是$HTTP_RAW_POST_DATA,因为它没有 依赖于特殊的php.ini指令。此外,对于那些情况 $HTTP_RAW_POST_DATA默认不填充,它是一个潜在的 较少的内存密集型替代激活 always_populate_raw_post_data。php://input不可用 enctype = " multipart /格式”。

特别要注意的是,不管你如何在web SAPI中访问它,php://输入流都是不可搜索的。这意味着它只能被读取一次。如果您工作在一个经常上传大型HTTP实体体的环境中,您可能希望以流形式维护输入(而不是像上面的第一个示例那样对其进行缓冲)。

为了维护流资源,这样做是有帮助的:

<?php

function detectRequestBody() {
    $rawInput = fopen('php://input', 'r');
    $tempStream = fopen('php://temp', 'r+');
    stream_copy_to_stream($rawInput, $tempStream);
    rewind($tempStream);

    return $tempStream;
}

php://temp允许您管理内存消耗,因为在存储了一定数量的数据(默认为2M)后,它会透明地切换到文件系统存储。这个大小可以在php.ini文件中操作,也可以通过追加/maxmemory:NN来操作,其中NN是在使用临时文件之前要保存在内存中的最大数据量,单位为字节。

当然,除非你有很好的理由在输入流上进行搜索,否则你不应该在web应用程序中使用这个功能。读取一次HTTP请求实体体通常就足够了——不要让客户端等待一整天,而你的应用程序却在思考该怎么做。

注意,php://input对于指定Content-Type: multipart/form-data报头(enctype="multipart/form-data"在HTML表单中)的请求是不可用的。这是因为PHP已经将表单数据解析为$_POST超全局变量。


检查$HTTP_RAW_POST_DATA变量


如果您已经安装了HTTP PECL扩展,您可以使用http_get_request_body()函数以字符串形式获取主体数据。


一个空$_POST的可能原因是请求不是POST,或者不再POST了…它可能开始是post,但在某处遇到301或302重定向,这被切换到GET!

检查$_SERVER['REQUEST_METHOD']以检查是否是这种情况。

有关为什么这种情况不应该发生,但仍然发生的良好讨论,请参阅https://stackoverflow.com/a/19422232/109787。


如果你安装了pecl/http扩展,你也可以使用这个:

$request = new http\Env\Request();
$request->getBody();

http_get_request_body()根据文档http://php.net/manual/fa/function.http-get-request-body.php显式地用于获取PUT和POST请求的主体


在数组中返回值

 $data = json_decode(file_get_contents('php://input'), true);

function getPost()
{
    if(!empty($_POST))
    {
        // when using application/x-www-form-urlencoded or multipart/form-data as the HTTP Content-Type in the request
        // NOTE: if this is the case and $_POST is empty, check the variables_order in php.ini! - it must contain the letter P
        return $_POST;
    }

    // when using application/json as the HTTP Content-Type in the request 
    $post = json_decode(file_get_contents('php://input'), true);
    if(json_last_error() == JSON_ERROR_NONE)
    {
        return $post;
    }

    return [];
}

print_r(getPost());

这是一个如何使用file_get_contents("php://input")创建一个php api的例子,并在javascript中使用ajax和XMLHttpRequest。

var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function () {
        if (this.readyState == 4 && this.status == 200) {
    console.log("done");
            }
        }
    };
    xhttp.open("POST", "http://127.0.0.1:8000/api.php", true);
    xhttp.send(JSON.stringify({
        username: $(this).val(),
        email:email,
        password:password
    }));

$data = json_decode(file_get_contents("php://input"));
$username  =  $data->username;
$email  =   $data->email;
$password  =   $data->password;