Laravel中间件创建内部请求后覆盖初始请求问题
问题解决:Laravel中间件内部请求覆盖原始请求
问题原因
你遇到的问题根源在于app()->handle($newRequest)会将传入的内部请求设置为Laravel容器中Illuminate\Http\Request的单例实例。一旦这个单例被替换,后续所有依赖请求实例的地方(包括中间件里的$request参数、控制器中注入的请求)都会指向这个内部请求,而非最初的原始请求。这就导致你给原始请求添加的参数未生效,反而内部请求的参数出现在了控制器日志里。
修复方案
方案1:通过Kernel实例处理内部请求(推荐)
使用Illuminate\Contracts\Http\Kernel实例处理内部请求,不会覆盖全局请求单例,还能完整执行请求生命周期:
public function handle(Request $request, Closure $next) { // 创建内部请求(直接在create方法中传入参数更简洁) $newRequest = Request::create('internal url', $method, [ 'temp_param_1' => 'value', 'temp_param_2' => 'value', ]); // 获取Kernel实例处理内部请求 $kernel = app()->make(\Illuminate\Contracts\Http\Kernel::class); $response = $kernel->handle($newRequest); $mixedResponse = json_decode($response->getContent(), true, 512, JSON_THROW_ON_ERROR); // 给原始请求添加参数 $request->merge([ 'new_value' => 'new_value', 'new_value_1' => $mixedResponse['new_value_id'] ]); // 终止内部请求的生命周期(释放资源) $kernel->terminate($newRequest, $response); return $next($request); }
方案2:处理完内部请求后恢复原始请求单例
若不想使用Kernel,可先保存原始请求单例,处理完内部请求后再恢复:
public function handle(Request $request, Closure $next) { // 保存原始请求的单例实例 $originalRequest = app()->get(Request::class); // 创建并处理内部请求 $newRequest = Request::create('internal url'); $newRequest->setMethod($method); $newRequest->merge([ 'temp_param_1' => 'value', 'temp_param_2' => 'value', ]); $response = app()->handle($newRequest); $mixedResponse = json_decode($response->getContent(), true, 512, JSON_THROW_ON_ERROR); // 恢复原始请求的单例 app()->instance(Request::class, $originalRequest); // 给原始请求添加参数 $request->merge([ 'new_value' => 'new_value', 'new_value_1' => $mixedResponse['new_value_id'] ]); return $next($request); }
额外修正:控制器注入请求实例
你的控制器index方法未注入Request实例,需修正为:
use Illuminate\Http\Request; use Illuminate\Support\Facades\Log; public function index(Request $request) { Log::info($request->all()); }
内容的提问来源于stack exchange,提问作者Giacomo M
相关产品推荐
相关产品推荐

