PATCH和PUT请求不使用表单数据

时间:2018-06-05 04:15:06

标签: php laravel http postman

我正在使用Laravel创建RESTFUL应用程序,并使用Postman测试应用程序。目前,如果从邮差发送的数据包含表单数据,则PATCHPUT会出现问题。

// Parameter `{testimonial}` will be sent to backend.
Route::post  ('testimonials/{testimonial}', 'TestimonialController@update');

// Parameter `{testimonial}` will not be sent to backend (`$request->all()` will be empty) if sent from Postman with form-data.
Route::patch ('testimonials/{testimonial}', 'TestimonialController@update');
Route::put   ('testimonials/{testimonial}', 'TestimonialController@update');
  • 使用表单数据,$request->all()可以使用POST
  • 使用x-www-form-urlencoded,$request->all()PATCHPUT可以使用POST
  • 但是,如果我发送PUTPATCH来自Postman的表单数据,则$request->all()将为空(参数不会发送到后端)。

现在解决方案是使用POST来更新模型。我想知道为什么PATCHPUT在使用Postman的表单数据发送时无效。

9 个答案:

答案 0 :(得分:19)

在这篇文章中,我学会了如何解决它,我想分享我的工作。

以下图像是我设置邮递员以发送 HTTP POST 请求并进入 PUT 请求并使其接收我的文件的方式。

我不确定这是否是执行RESTFul API的正确方法。 但是效果很好

An example on Postman how to setup your HTTP Request

答案 1 :(得分:6)

这是一个已知问题,根据以下Github comment的解决方案建议是,在发送PATCH / PUT请求时,您应该执行以下操作:

  

您应发送POST并将_method设置为PUT(与发送表单相同)以使您的文件可见

所以基本上你发送一个带有参数的POST请求,该参数设置实际的方法,Laravel似乎明白这一点。

根据documentation

  

由于HTML表单无法生成PUTPATCHDELETE个请求,因此您需要添加一个隐藏的_method字段来欺骗这些HTTP动词。 @method Blade指令可以为您创建此字段:

<form action="/foo/bar" method="POST">
    @method('PUT')

    ...
</form> 

或者,您可以使用method_field帮助函数执行上述操作:

  

method_field函数生成一个HTML隐藏输入字段,其中包含表单的HTTP谓词的欺骗值。例如,使用Blade语法:

<form method="POST">
    {{ method_field('PUT') }}
</form>

答案 2 :(得分:4)

因此,正如以上每个人所提到的,并解释了所有内容,但是在使用REST API的情况下,我仍然看不到答案,所以我不愿@Caique Andrade回答并发送POST请求并形成我的URL链接,如下所示:

url = 'https://yourwebsite.com/api/v1/users/$id?_method=PUT';

$id是用户的变量ID。

?_method=PUT被添加到URL POST请求中,以欺骗请求,并且有效

在我的情况下,我在扑打中使用了Dart并使用Http包Laravel发送了一个post请求,将那个POST请求作为PUT请求捕获了

答案 3 :(得分:2)

Laravel PATCH和PUT方法不适用于form-data,它是Symfony甚至PHP的已知问题(谷歌为此--Laravel使用许多Symfony基础包,包括请求)。

  1. 如果您不需要通过请求传递文件,请使用json content-type将form-data更改为raw。例如:{"name":"changed"}。它将被视为php://input,您的代码应运行良好($request->all()现在为["name" => "changed])。

  2. 如果您需要传递文件,我认为不要在REST API方法中传递它。您可以编写另一种方法来对文件执行任何操作(例如:POST form-data - &gt;上传文件 - &gt;更新数据库 - &gt;返回文件路径/网址/甚至其base64内容),然后你可以使用它的输出/结果继续你的补丁/ put方法(raw与json内容类型)。当我使用API​​中的文件时,我总是这样做。

  3. 希望这有帮助!

答案 4 :(得分:2)

如上所述,这不是symfony(或laravel,或任何其他框架)问题,而是PHP的局限性。

在为php内核浏览了很多RFC之后,核心开发团队似乎有点抵制实现与现代化HTTP请求处理有关的任何事情。该问题最早是在2011年报告的,它看起来似乎离本机解决方案还差得远。

也就是说,我设法找到了this PECL extension。我对pecl并不是很熟悉,而且似乎无法使用pear来工作。但是我正在使用具有yum软件包的CentOS和Remi PHP。

我运行了yum install php-pecl-apfd并从字面上解决了这个问题(我不得不重启我的docker容器,但这是给定的。)

也就是说,request->all()files->get()开始使用multipart/form-data处理PATCH和PUT请求。

我相信还有其他各种Linux风格的软件包,我相信任何对pear / pecl / general php扩展有更多了解的人都可以使其在Windows或Mac上正常运行。

答案 5 :(得分:0)

表单媒体类型没有为PATCH定义任何语义,因此使用它们确实是个坏主意(参见https://www.rfc-editor.org/errata/eid3169)。

对于PUT,预期的行为是仅存储表单编码的有效负载(以该格式)。这真的是你想要的吗?

答案 6 :(得分:0)

正如@DazBaldwin所说,这是php的局限性,可以解决安装apfd扩展名的问题。 在Windows 上,根据您的系统设置下载dll文件here,然后将php_apfd.dll放在 path-to-php / ext 目录中,最后将 php.ini文件中的extension = apfd

它在Windows上对我有用。

答案 7 :(得分:0)

InertiaJS 解决方案

我遇到了同样的问题。当没有发送文件时,一切正常,但是当我发送文件时,没有任何字段进入后端。

好像是 PHP 的限制,没有通过 put 接收文件,如前所述。

因此,对于那些使用 InertiaJS 的人,您需要制作一个 post - 而不是 put - 调用并将 _method: "put" 添加到您的惯性表单中,例如这个:

updateForm: this.$inertia.form({
            _method: "put",
            "other fields"
        }),

您的控制器会像PUT调用一样理解它,但后端可以访问该文件。

来源: https://inertiajs.com/manual-visits#method

答案 8 :(得分:-1)

您可以使用 post 方法。 const 形式 = 新 只需追加 form.append('_method', 'PATCH');