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 请求的流程:
- 全局中间件运行
- 目标控制器的
__construct
运行 - 组中间件运行
- 目标控制器的方法/操作运行(在上述情况下
index
)
试试这个
public function register()
{
$this->app->bind('MyInterface', function ($app) {
return new MyImplementation(request()->foo);
}
}