You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel 9测试环境下AppServiceProvider中request()->all()返回空数据

Laravel测试环境下AppServiceProvider无法获取请求参数的解决方案

问题根源

测试环境执行php artisan test时,AppServiceProvider的boot方法在测试请求初始化前就已执行,导致request()助手无法获取当前请求的参数;而生产环境中,HTTP请求先于服务提供者的boot流程完成初始化,所以逻辑正常运行。

解决方案

方案一:延迟绑定(推荐)

将绑定逻辑从boot方法移至register方法,使用闭包延迟解析——只有当MyFactory被实际注入时,才执行请求参数判断,此时请求已完全就绪。

修改AppServiceProvider代码:

<?php

namespace App\Providers;

use App\Http\Requests\MySimpleRequest;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\ServiceProvider;
use App\Http\Requests\abstract\MyFactory;
use App\Http\Requests\MyExpRequest;
use Illuminate\Http\Resources\Json\JsonResource;

class AppServiceProvider extends ServiceProvider
{
    public function register()
    {
        // 延迟绑定:当MyFactory被解析时才执行判断逻辑
        $this->app->bind(MyFactory::class, function ($app) {
            $request = $app->make('request');
            return $request->input('exp') !== null 
                ? $app->make(MyExpRequest::class) 
                : $app->make(MySimpleRequest::class);
        });
    }

    public function boot()
    {
        // 保留原有的其他boot逻辑,移除之前的绑定代码
    }
}

方案二:路由中间件绑定

通过中间件在请求进入路由后执行绑定逻辑,此时请求参数已完全可用。

  1. 创建中间件:
php artisan make:middleware BindRequestFactory
  1. 编写中间件逻辑:
<?php

namespace App\Http\Middleware;

use Closure;
use App\Http\Requests\abstract\MyFactory;
use App\Http\Requests\MyExpRequest;
use App\Http\Requests\MySimpleRequest;

class BindRequestFactory
{
    public function handle($request, Closure $next)
    {
        app()->bind(MyFactory::class, function ($app) use ($request) {
            return $request->has('exp') 
                ? $app->make(MyExpRequest::class) 
                : $app->make(MySimpleRequest::class);
        });

        return $next($request);
    }
}
  1. 注册中间件:
    在app/Http/Kernel.php的api中间件组中添加该中间件:
protected $middlewareGroups = [
    'api' => [
        // 其他已有中间件
        \App\Http\Middleware\BindRequestFactory::class,
    ],
];

方案三:工厂类直接处理

重构MyFactory为静态工厂类,直接在需要的地方调用获取实例:

<?php

namespace App\Http\Requests\abstract;

use App\Http\Requests\MyExpRequest;
use App\Http\Requests\MySimpleRequest;

class MyFactory
{
    public static function create()
    {
        return request()->has('exp') 
            ? new MyExpRequest() 
            : new MySimpleRequest();
    }
}

在控制器或其他业务代码中,直接使用MyFactory::create()替代依赖注入即可。

测试验证

原测试代码无需修改,发送带exp参数的请求时,会自动触发对应的FormRequest绑定逻辑:

$transSactionData = [
   'data'=>1,
   'user'=>123,
   'exp'=>1
];

$response = $this->post('/api/order',$transSactionData);

内容的提问来源于stack exchange,提问作者David Ko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 01:01:35