PSR-7:getParsedBody() 与 getBody()

PSR-7: getParsedBody() vs getBody()

场景 1 发送 x-www-form-urlencoded 数据

POST /path HTTP/1.1
Content-Type: application/x-www-form-urlencoded

foo=bar

运行 print_r($request->getParsedBody()); returns 很好:

Array
(
    [foo] => bar
)

运行 print_r($request->getBody()->getContents()); returns 一个字符串 foo=bar


场景2发送application/json数据

POST /path HTTP/1.1
Content-Type: application/json

{
    "foo": "bar"
}

运行 print_r($request->getParsedBody()); returns 一个空数组。 Array ( )

但是,运行 print_r($request->getBody()->getContents()); returns 很好:

{"foo":"bar"}


这是预期的行为吗?

意思是,如果我们要发送 x-www-form-urlencoded 数据,我们应该使用 getParsedBody()

如果我们要发送 application/json,则应使用 getBody()->getContents()?


附加信息:

请求对象是使用以下方法创建的:

$request = \Laminas\Diactoros\ServerRequestFactory::fromGlobals(
        $_SERVER, $_GET, $_POST, $_COOKIE, $_FILES
);

留言body:

在 PSR-7 库中,消息 bodyStreamInterface 提取。此接口的任何实现必须包装一个 PHP stream and, of course, should provide the proper functionality to perform the specific read/write/seek operations on it. PHP provides a list of I/O streams,其中 php://input 适合所讨论的任务。

php://input is a read-only stream that allows you to read raw data from the request body. php://input is not available with enctype="multipart/form-data".

在此上下文中,当执行对服务器的请求时,请求 body 数据(无论其数据类型如何)自动写入 php://input 流,原始格式(字符串).稍后可以通过调用 StreamInterface::getContentsStreamInterface::__toStringStreamInterface::read(可能会在其实现中使用 stream_get_contents() 或类似方法)从中读取信息。

注:当object代表消息[=122]时,自动调用方法StreamInterface::__toString =],例如class 实现 StreamInterface 的实例被转换为字符串。例如,像这样 - 参见 PHP 中的 Type Casting:

$messageBodyObject = $request->getBody(); // implements StreamInterface
$contentOfMessageBody = (string) $messageBodyObject; // cast to string => StreamInterface::__toString is called

echo $contentOfMessageBody;

已解析 body:

关于 PSR-7,解析的 body 是应用程序的“特征”,其中 PHP 是 “用作 server-side 应用程序来完成 HTTP 请求”(与 PHP 用作 “HTTP 客户端” 的应用程序相比) - 见 Summary of the PSR-7 Meta Document。所以,解析的body只是ServerRequestInterface的一个组成部分。

解析的body(阅读ServerRequestInterface::getParsedBodyServerRequestInterface::withParsedBody的注释)被认为是“解析”形式的表示作为执行请求的结果保存在 php://input 流中的原始数据(字符串)的(数组或 object)。例如,$_POST variable 是一个数组,它包含 已解析的 body POST 请求,在下面给出的条件下。

相关use-cases:

如果执行POST请求并且header Content-Typeapplication/x-www-form-urlencoded(例如当提交一个普通的HTML表单时),内容请求的 body 自动保存到 php://input 流(序列化)和 $_POST 变量(数组)中。因此,在 PSR-7 上下文中,同时调用 StreamInterface::getContents(或 StreamInterface::__toString,或 StreamInterface::read)和 ServerRequestInterface::getParsedBody 将 return“有效”值。

如果执行 POST 请求并且 header Content-Typemultipart/form-data(例如执行文件上传时),则请求 body 根本不会保存到 php://input 流中,而只会保存到 $_POST 变量(数组)中。因此,在 PSR-7 上下文中,只有调用 ServerRequestInterface::getParsedBody 才会 return 一个“有效”值。

如果执行了 POST 请求,并且 header Content-Type 具有除上述两个之外的其他值(例如 application/json,或 text/plain; charset=utf-8 ),请求 body 的内容仅保存到 php://input 流中。因此,在 PSR-7 上下文中,仅调用 StreamInterface::getContents(或 StreamInterface::__toStringStreamInterface::read)将 return 一个“有效”值。

资源: