Laravel向API端点发送变量为空的问题排查求助
问题描述
我尝试从Laravel控制器向API端点发送表单数据(含文件),但API端检查变量时所有值均为null。已通过dd($multipart)确认提交时表单数据完整,相关代码片段如下:
后台控制器(CulinaryController.php)
public function update(Request $request, Culinary $culinary) { $client = new Client(); $token = Session('token'); try { $multipart = []; foreach ($request->except('cover_photo') as $key => $value) { $multipart[] = [ 'name' => $key, 'contents' => $value, ]; } if ($request->hasFile('cover_photo')) { $coverPhoto = $request->file('cover_photo'); $multipart[] = [ 'name' => 'cover_photo', 'contents' => fopen($coverPhoto->getRealPath(), 'r'), 'filename' => $coverPhoto->getClientOriginalName(), ]; } dd($multipart); $url = 'http://localhost/api/v1/culinary/'.$culinary->id; $response = $client->put($url, [ 'multipart' => $multipart, 'headers' => [ 'Authorization' => 'Bearer '.$token, 'Accept' => 'application/json', ] ]); } catch (Exception $e) { return redirect()->back()->withErrors(['errors' => $e->getMessage()])->withInput(); } }
API控制器(api/v1/CulinaryController.php)
public function update(Request $request, Culinary $culinary) { return response()->json([ 'status' => 'test', 'request' => $request->all(), 'foo' => request('title'), 'file' => $request->file('cover_photo'), 'culinary' => $culinary, ]); }
API路由(routes/api.php)
Route::apiResource('culinary', CulinaryController::class);
dd($multipart)输出的数据示例
array:9 [▼ // app\Http\Controllers\AdminCulinaryController.php:198 0 => array:2 [▼ "name" => "_token" "contents" => "TwpS0e7OJH1jhhR1dr8RBpCiYKW4vhVyuk3CRZWC" ] 1 => array:2 [▼ "name" => "_method" "contents" => "PUT" ] 2 => array:2 [▼ "name" => "title" "contents" => "Et in quia ut et illo harum." ] 3 => array:2 [▼ "name" => "old_cover_photo" "contents" => "https://via.placeholder.com/640x480.png/0022bb?text=distinctio" ] 4 => array:2 [▼ "name" => "country_id" "contents" => "188" ] 5 => array:2 [▼ "name" => "category_name" "contents" => "vegetarian" ] 6 => array:2 [▼ "name" => "prologue" "contents" => "Adipisci iure nihil sit voluptatem rerum voluptatibus. Qui aperiam et magnam corrupti quia eius reprehenderit. Sunt non aut dolores. Dolorem nesciunt atque ipsa ▶" ] 7 => array:2 [▼ "name" => "body" "contents" => "Autem iure qui magni excepturi hic. Laudantium adipisci saepe odio quod cupiditate. Blanditiis occaecati sint at sint incidunt optio illum nihil." ] 8 => array:2 [▼ "name" => "opening_hours" "contents" => "Qui et magnam labore a ea corrupti." ] ]
问题排查与解决
核心原因:Laravel默认仅解析POST方法的multipart/form-data请求体,直接用PUT方法发送multipart请求时,框架无法自动解析表单数据,导致所有值为null。
方案一:改用POST方法伪造PUT请求(推荐)
调整Guzzle请求方法为POST,同时保留_method=PUT的字段(已包含在multipart中):
// 替换原PUT请求代码 $response = $client->post($url, [ 'multipart' => $multipart, 'headers' => [ 'Authorization' => 'Bearer '.$token, 'Accept' => 'application/json', ] ]);
Laravel会识别_method字段,自动将请求视为PUT请求,同时正常解析multipart数据。
方案二:添加中间件支持PUT/PATCH的multipart解析
创建中间件app/Http/Middleware/ParseMultipartPut.php:
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; class ParseMultipartPut { public function handle(Request $request, Closure $next) { if (in_array($request->method(), ['PUT', 'PATCH']) && $request->isMultipartContent()) { $request->merge($request->all()); foreach ($request->files->all() as $key => $file) { $request->files->set($key, $file); } } return $next($request); } }
在app/Http/Kernel.php的api中间件组中注册该中间件:
protected $middlewareGroups = [ 'api' => [ // 原有中间件... \App\Http\Middleware\ParseMultipartPut::class, ], ];
验证修复效果
修改API控制器返回内容,确认数据是否正常获取:
public function update(Request $request, Culinary $culinary) { return response()->json([ 'status' => 'success', 'all_data' => $request->all(), 'title' => $request->input('title'), 'has_cover_photo' => $request->hasFile('cover_photo'), 'culinary_id' => $culinary->id ]); }
内容的提问来源于stack exchange,提问作者dapidmini
相关产品推荐
相关产品推荐

