【问题标题】:PHP get PUT request bodyPHP 获取 PUT 请求正文
【发布时间】:2017-07-31 23:00:07
【问题描述】:

我目前正在用 PHP 开发一个 Restful Json-API。我想向items/:id 发送 PUT 请求以更新记录。数据将以application/json 传输。

我想调用 API

curl -H "Content-Type: application/json" -X PUT -d '{"example" : "data"}' "http://localhost/items/someid"

在服务器端,我无法检索请求正文。我试过了

file_get_contents("php://input");

但这会返回一个空字符串。 fopen()/fread() 组合也不起作用。

通过 POST 调用时,一切正常,我可以在服务器端完美读取 json。但是 API 不再是 Restful。有人对此有解决方案吗?还有另一种发送和接收 Json 的方法吗?

顺便说一句,我正在使用 Slim Framework 开发 API。

【问题讨论】:

  • 你试过 fopen("php://input", "r") 吗?
  • 太棒了,您正在使用 slim。我希望你有很好的经验。我真的很喜欢我的 SLIM restful api 创作
  • 手册中的 This comment 建议您可能需要发送 Content-Length 标头(不确定 cURL 是否会自动执行此操作...)并使用 fopen,而不是 file_get_contents .不知道这有多准确,但可能值得一试......
  • curl 确实发送了 Content-Length 标头,并且在手动发送时也没有任何变化。 fopen 也不起作用。

标签: php json rest


【解决方案1】:

php://input 对于 PUT 请求只能读取一次:

注意:使用 php://input 打开的流只能读取一次;该流不支持查找操作。但是,根据 SAPI 实现,可能会打开另一个 php://input 流并重新开始读取。这只有在请求正文数据已保存时才有可能。通常,这是 POST 请求的情况,但不是其他请求方法,例如 PUT 或 PROPFIND。

http://php.net/manual/en/wrappers.php.php

Slim 框架已根据请求读取数据。从已读入的 Request 对象中获取数据。

【讨论】:

  • 非常感谢,这解决了我的问题。我可以使用 $app->request->getBody(); 获取原始数据;然后做一个 json_decode。我不知道这种方法,因为它不在文档中。
  • +1 这是我使用 restTonic PHP 框架的问题。 $this->request->data 变量已经保存了 PUT 主体。我在我的 POST 处理程序中阅读了 php://input,但看不出为什么 PUT 处理程序不能使用相同的方法来处理它的主体。
【解决方案2】:

在服务器端,我无法检索请求正文。我试过 file_get_contents("php://input");

每个请求您只能使用一次file_get_contents( 'php://input', 'r' );。检索它的值也会截断值,所以如果你调用它两次,它会返回一个空字符串。 Slim 的请求对象包含你需要的值,所以:

<?php
$app = new Slim( );

$app->put( '/items/someid', function () use ( $app ) {
    echo $app->request( )->put( 'example' ); // should display "data".
});

【讨论】:

  • 这适用于 url 编码的数据,但不适用于原始 json。如果我发送编码的数据 url,我可以通过 Slim 的请求对象访问它。不适用于 json 强硬。
  • 问题依然存在;你只能从 php://input once 中读取,而 Slim 已经做到了。您必须使用 Slim 的请求对象来获取您的值。
  • 显然 Slim 框架在构造时会读取请求正文,因此 php://input 已被删除。谢谢!
  • @aladin 这就是我想要传达的,是的。
【解决方案3】:

PHP manual 中的示例使用 fopen 以读取模式访问 php://input。您是否尝试过这样做?

编辑:manual page for PHP:// 说了一些似乎暗示 PUT 数据在某些情况下可能不可用的内容!

注意:使用 php://input 打开的流只能读取一次;这 流不支持查找操作。但是,根据 SAPI实现,可能可以另开一个php://input 流并重新开始阅读。仅当请求正文 数据已保存。通常,这是 POST 请求的情况, 但不是其他请求方法,例如 PUT 或 PROPFIND。

对于 PUT 处理,我不知道这会给您带来什么影响。一页似乎说这是可能的,另一页似乎暗示它在错误的情况下不起作用

【讨论】:

    【解决方案4】:

    前几天我正在阅读 SLIM 框架文档,它说某些浏览器在 PUT 和 DELETE 方面存在问题。

    摘录:

    不幸的是,现代浏览器不提供对 PUT 请求的原生支持。要解决此限制,请确保您的 HTML 表单的方法是“post”,然后向您的 HTML 表单添加一个方法覆盖参数,如下所示:

    <form action="/books/1" method="post">
        ... other form fields here...
        <input type="hidden" name="_METHOD" value="PUT"/>
        <input type="submit" value="Update Book"/>
    </form>
    

    来源:http://www.slimframework.com/documentation/stable

    【讨论】:

    • OP 正在使用 Curl 执行 HTTP PUT 操作。
    • 我对此也有点陌生,但 cURL 是否只是放弃了浏览器问题?如果他正在通过 PHP 执行 curl 请求并且这与命令行等效怎么办? (我不是说他是,我是说命令行 cURL 的好处是否仍然存在)
    • @Jake:是的,使用 cURL 可以解决浏览器问题。他调用服务的方式不涉及浏览器。
    • curl 生成原始 HTTP 请求,您可以完全控制请求的每一个细节。 PUT/POST 只是一个 HTTP 动词,您可以在命令行上使用 -X PUT 设置它,在其他包装器中使用类似的标志。是的,curl 支持 PUT,只有浏览器不支持。
    猜你喜欢
    • 1970-01-01
    • 2022-08-19
    • 1970-01-01
    • 1970-01-01
    • 2017-03-10
    • 2011-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多