首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PSR-7: getParsedBody()与getBody()

PSR-7: getParsedBody()与getBody()
EN

Stack Overflow用户
提问于 2020-02-06 18:54:21
回答 2查看 2.9K关注 0票数 5

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

代码语言:javascript
复制
POST /path HTTP/1.1
Content-Type: application/x-www-form-urlencoded

foo=bar

运行print_r($request->getParsedBody());会返回很好的结果:

代码语言:javascript
复制
Array
(
    [foo] => bar
)

运行print_r($request->getBody()->getContents());将返回字符串foo=bar

场景2发送application/json数据

代码语言:javascript
复制
POST /path HTTP/1.1
Content-Type: application/json

{
    "foo": "bar"
}

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

但是,运行print_r($request->getBody()->getContents());返回很好的结果:

{"foo":"bar"}

这是预期的行为吗?

也就是说,如果我们发送x-www-form-urlencoded数据,我们应该使用getParsedBody()

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

附加信息:

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

代码语言:javascript
复制
$request = \Laminas\Diactoros\ServerRequestFactory::fromGlobals(
        $_SERVER, $_GET, $_POST, $_COOKIE, $_FILES
);
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-02-09 20:07:47

消息体:

在PSR-7库中,消息体由StreamInterface抽象.这个接口的任何实现都必须包装一个PHP流,当然,它应该提供适当的功能来执行特定的读/写/查找操作。PHP提供了一个I/O 列表,其中php://input适合于所讨论的任务。

php://input是一个只读流,允许您从请求体读取原始数据。php://input在enctype=“多部分/表单-数据”中不可用。

在这种情况下,当执行对服务器的请求时,请求体数据(不管其数据类型如何)会以原始格式(string)自动写入php://input流。稍后可以通过调用StreamInterface::getContentsStreamInterface::__toStringStreamInterface::read (这可能会在实现中使用stream_get_contents()或类似的方法)从其中读取信息。

注意:当表示消息体的对象(例如,实现StreamInterface的类的实例被转换为字符串)时,方法StreamInterface::__toString被自动调用。例如,请参见PHP中的型铸造

代码语言:javascript
复制
$messageBodyObject = $request->getBody(); // implements StreamInterface
$contentOfMessageBody = (string) $messageBodyObject; // cast to string => StreamInterface::__toString is called

echo $contentOfMessageBody;

解析体:

关于PSR-7,解析体是PHP“用作服务器端应用程序来完成HTTP请求”的应用程序的“特征”(与使用PHP作为“HTTP”的应用程序相比)-请参阅PSR-7元文件摘要。因此,解析的主体仅是ServerRequestInterface的一个组件。

被解析的主体(读取ServerRequestInterface::getParsedBodyServerRequestInterface::withParsedBody的注释)被认为是由于执行请求而保存在php://input流中的原始数据(字符串)的“解析”形式(数组或对象)中的表示。例如,后变量是一个数组,它在下面所示的条件下保存POST请求的解析体。

相关用例-用例:

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

如果执行POST请求,头Content-Typemultipart/form-data (例如,在执行文件上载时),则请求主体的内容根本不保存到php://input流中,而是只保存到$_POST变量(数组)中。因此,在PSR-7上下文中,只有调用ServerRequestInterface::getParsedBody才会返回“有效”值。

如果执行了POST请求,并且报头Content-Type具有上述两个值以外的其他值(例如,application/jsontext/plain; charset=utf-8),则请求主体的内容仅保存到php://input流中。因此,在PSR-7上下文中,只有调用StreamInterface::getContents (或StreamInterface::__toString,或StreamInterface::read)才会返回“有效”值。

资源:

票数 9
EN

Stack Overflow用户

发布于 2022-09-10 11:33:37

@dakis的答案是正确的,但我发现它在回答场景2失败的最初问题时有点含糊。

从PSR的角度来看,这种行为是正确的(正如@dakis所说):

  • 主体将流返回给请求体。
  • parsedBody是请求的一个特性,可以包含对主体的解析表示(但不是必需的),如PHPDoc of ServerRequestInterface::getParsedBody中所提到的: 否则,此方法可能返回反序列化请求主体内容的任何结果;.

从有用的角度看,层流式的对话是缺乏的,在我看来,也是半生不熟的。这个库似乎只会传递已经被PHP解析的数据($_GET/$_POST.)。更好的实现应该处理用于parsedBody的特定内容类型,并且会自动抛出或处理坏的POST数据。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60101751

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档