Laravel中多次构造单例绑定

时间:2018-11-03 10:02:03

标签: laravel

在我的服务提供者中,我将类与单例绑定在一起:

public function register()
{
    $this->app->singleton('ResourceContainer', function($app){
        return new ResourceContainer();
    });
}

laravel重复说明说该类将被解析一次,并且将返回相同的对象:

  

单例方法将类或接口绑定到只能解析一次的容器中。解决单例绑定后,在随后的容器调用中将返回相同的对象实例:

但是在我的应用中,ResourceContainer的构造函数被调用了两次。

我想在serviceprovider的启动方法中调用此实例:

public function boot()
{
    $resourceContainer = $this->app->make('ResourceContainer');

然后将类注入控制器:

public function index(ResourceContainer $container, $resource){

当我调试时,ResourceContainer的构造函数被调用两次。我在控制器中得到的对象不同于服务提供者的引导方法中的对象。

2 个答案:

答案 0 :(得分:2)

您应该绑定fully qualified class name

$this->app->singleton(ResourceContainer::class, function($app){
    return new ResourceContainer();
});

并以相同的方式使用它:

$resourceContainer = $this->app->make(ResourceContainer::class);

问题是您要处理两个不同的字符串:

'ResourceContainer'
'Foo\Bar\ResourceContainer'

绑定'ResourceContainer'时,...->make('ResourceContainer')将正确解析您的单身人士。

但是,当您使用依赖项注入时:

public function index(ResourceContainer $container, $resource) {}

Laravel尝试从容器中解析完全限定的类名'Foo\Bar\ResourceContainer'。由于此字符串尚未绑定到容器,因此Laravel足够“聪明”,可以使用反射来自动解析类并注入 new 实例。

答案 1 :(得分:2)

原因是您请求的对象不同。基本上可以归结为以下两行代码:

$resourceContainer = $this->app->make('ResourceContainer');
public function index(ResourceContainer $container) { ... } // simplified

由于您很可能没有将ResourceContainer类放在全局命名空间中,而是可能在App\Services\ResourceContainer之类的地方,因此需要从服务容器中请求该名称。因此,由于该类位于该命名空间中,因此在类中进行类型提示实际上会在后台调用$this->app->make('App\Services\ResourceContainer')

因此,解决方案非常简单:在类的名称下注册单例,并将手动调用更改为make($class)。键入提示将立即可用。

public function register()
{
    $this->app->singleton(ResourceContainer::class, function($app) {
        return new ResourceContainer();
    });
}