我正在使用Laravel创建RESTFUL应用程序,并使用Postman测试应用程序。目前,如果从邮差发送的数据包含表单数据,则PATCH
或PUT
会出现问题。
// 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
。$request->all()
,PATCH
和PUT
可以使用POST
。PUT
和PATCH
来自Postman的表单数据,则$request->all()
将为空(参数不会发送到后端)。现在解决方案是使用POST
来更新模型。我想知道为什么PATCH
和PUT
在使用Postman的表单数据发送时无效。
答案 0 :(得分:19)
在这篇文章中,我学会了如何解决它,我想分享我的工作。
以下图像是我设置邮递员以发送 HTTP POST 请求并进入 PUT 请求并使其接收我的文件的方式。
我不确定这是否是执行RESTFul API的正确方法。 但是效果很好
答案 1 :(得分:6)
这是一个已知问题,根据以下Github comment的解决方案建议是,在发送PATCH
/ PUT
请求时,您应该执行以下操作:
您应发送POST并将_method设置为PUT(与发送表单相同)以使您的文件可见
所以基本上你发送一个带有参数的POST请求,该参数设置实际的方法,Laravel似乎明白这一点。
由于HTML表单无法生成
PUT
,PATCH
或DELETE
个请求,因此您需要添加一个隐藏的_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基础包,包括请求)。
如果您不需要通过请求传递文件,请使用json content-type将form-data
更改为raw
。例如:{"name":"changed"}
。它将被视为php://input
,您的代码应运行良好($request->all()
现在为["name" => "changed]
)。
如果您需要传递文件,我认为不要在REST API方法中传递它。您可以编写另一种方法来对文件执行任何操作(例如:POST form-data
- &gt;上传文件 - &gt;更新数据库 - &gt;返回文件路径/网址/甚至其base64内容),然后你可以使用它的输出/结果继续你的补丁/ put方法(raw
与json内容类型)。当我使用API中的文件时,我总是这样做。
希望这有帮助!
答案 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)
我遇到了同样的问题。当没有发送文件时,一切正常,但是当我发送文件时,没有任何字段进入后端。
好像是 PHP 的限制,没有通过 put 接收文件,如前所述。
因此,对于那些使用 InertiaJS 的人,您需要制作一个 post - 而不是 put - 调用并将 _method: "put"
添加到您的惯性表单中,例如这个:
updateForm: this.$inertia.form({
_method: "put",
"other fields"
}),
您的控制器会像PUT调用一样理解它,但后端可以访问该文件。
答案 8 :(得分:-1)
您可以使用 post 方法。 const 形式 = 新 只需追加 form.append('_method', 'PATCH');