应用中间件后在服务提供商中的访问请求



Bindings

我在接口和实现之间的服务提供商中使用绑定:

public function register()
{
    $this->app->bind('MyInterface', MyImplementation::class);
}

中间件

在我的中间件中,我向请求添加一个属性:

public function handle($request, Closure $next)
{
    $request->attributes->add(['foo' => 'bar]);
    return $next($request);
}

现在,我想访问服务提供商中的foo

public function register()
{
    $this->app->bind('MyInterface', new MyImplementation($this->request->attributes->get('foo')); // Request is not available
}

在应用中间件之前调用 register()。我知道。

我正在寻找一种在设置了请求>属性>get('foo')时"重新绑定"的技术

尝试如下:

public function register()
{
    $this->app->bind('MyInterface', function () {
        $request = app(IlluminateHttpRequest::class);
        return app(MyImplementation::class, [$request->foo]);
    }
}

绑定元素的工作方式如下,只有在调用它们时才会触发它们。

service provider 您还可以通过以下方式访问Request Object

public function register()
{
    $request = $this->app->request;
}

接受的答案很好,但它没有解决有关 DI 的问题。因此,在您的服务提供商中,您需要:

public function register()
{
    $this->app->bind('MyInterface', function () {
        return new MyImplementation(request()->foo);
    }
}

但是您需要小心DI。如果在控制器中执行此操作:

class MyController extends Controller
{
    public function __construct(MyInterface $myInterface)
    {
        $this->myInterface = $myInterface;
    }
}

这是行不通的!控制器的构造函数在应用组中间件之前被调用,因此foo参数将在MyImplementation上为 null。

如果要使用 DI,则需要使用构造函数外部的App::make(MyInterface::class)来解决它,或者更好地在控制器的方法中传递依赖项:

class MyController extends Controller
{
    public function index(MyInterface $myInterface)
    {
        $myInterface->getFoo();
    }
}

上面会起作用,因为控制器的方法在应用中间件执行。

这是 laravel 请求的流程:

  1. 全局中间件运行
  2. 目标控制器的__construct运行
  3. 组中间件运行
  4. 目标控制器的方法/操作运行(在上述情况下index

试试这个

public function register()
{
    $this->app->bind('MyInterface', function ($app) {
        return new MyImplementation(request()->foo);
    }
}

最新更新