Laravel API以formData提交更新请求无数据如何排查解决
Laravel update接口formData请求参数丢失排查
问题表现
- 基于Laravel开发API时,update接口无法获取formData格式提交的参数,导致数据表更新异常
- 使用Postman测试时,同控制器下的POST类型接口可正常读取formData参数,仅update方法拿不到请求数据
- 问题相关业务代码如下:
public function update(Request $request,$id) { $data = [ 'name' => $request->name, 'descrip' => $request->descrip, 'amount' => $request->amount, ]; $spent = Spending::find($id); $spent->update($data); return response()->json(['success' => true, 'data' => $spent]); }
根本原因
PHP原生仅会自动解析POST请求的multipart/form-data(即formData格式)请求体,自动填充$_POST超全局变量;对于PUT/PATCH类型的请求,不会自动解析该格式的请求数据。
Laravel默认资源路由中update方法对应的请求方法是PUT/PATCH,如果直接在Postman中选择PUT方法提交formData,框架无法自动解析请求体参数,就会出现参数取不到的问题,这也是POST接口正常、update接口异常的核心原因。
可行解决方案
方案1:POST请求携带_method参数模拟PUT(推荐)
这是Laravel官方支持的请求方法伪造方案,适配成本最低:
- 将Postman的请求方法设置为
POST,请求地址保持原update接口地址不变 - 在formData参数中新增参数
_method,参数值设为PUT - 正常提交其他业务参数即可,Laravel会自动识别
_method参数,将请求转发到对应的update方法,同时可以正常解析所有formData参数
方案2:调整路由请求方法为POST
如果不需要严格遵循RESTful路由规范,可以直接将路由文件中对应update接口的请求方法从PUT/PATCH改为POST,修改后该接口和普通POST接口逻辑完全一致,可直接读取formData参数。
方案3:代码手动解析PUT请求的formData数据
如果业务要求必须使用原生PUT请求提交formData,可在控制器中手动读取原始请求体解析参数,参考实现:
public function update(Request $request,$id) { // 手动解析PUT请求的formData格式数据 if ($request->isMethod('PUT') && str_contains($request->header('Content-Type'), 'multipart/form-data')) { $raw = file_get_contents('php://input'); $boundary = substr($raw, 0, strpos($raw, "\r\n")); $parts = array_slice(explode($boundary, $raw), 1); $parsedData = []; foreach ($parts as $part) { if ($part == "--\r\n") break; $part = ltrim($part, "\r\n"); list($headers, $body) = explode("\r\n\r\n", $part, 2); $headerLines = explode("\r\n", $headers); foreach ($headerLines as $line) { if (str_starts_with($line, 'Content-Disposition:')) { preg_match('/name="([^"]+)"/', $line, $match); if (isset($match[1])) { $parsedData[$match[1]] = trim($body, "\r\n"); } } } } $request->merge($parsedData); } $data = [ 'name' => $request->name, 'descrip' => $request->descrip, 'amount' => $request->amount, ]; $spent = Spending::find($id); $spent->update($data); return response()->json(['success' => true, 'data' => $spent]); }
注意:该方案需要自行处理文件上传、特殊字符转义等边界场景,非必要不推荐使用。
内容的提问来源于stack exchange,提问作者Soporte Tecnico
相关产品推荐
相关产品推荐

