在Laravel中,单例绑定被多次构建

6 浏览
0 Comments

在Laravel中,单例绑定被多次构建

在我的服务提供者中,我绑定了一个单例类:

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

Laravel文档中说,这个类将被解析一次,并且将返回相同的对象:

singleton方法将一个类或接口绑定到容器中,应该只解析一次。一旦解析了一个单例绑定,后续对容器的调用将返回相同的对象实例:

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

我想在服务提供者的boot方法中调用这个实例:

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

并且我在控制器中注入了这个类:

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

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

0
0 Comments

问题的原因是在Laravel中,使用自动依赖注入时,绑定的字符串键与完全限定类名不匹配,导致单例绑定多次构建的问题。解决方法是使用`::class`语法来绑定和引用类。

在Laravel中,使用`singleton`方法进行绑定时,可以使用`::class`语法来指定类名。例如:

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

而在使用`make()`方法时,也可以使用同样的`::class`语法来引用类。例如:

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

问题出现的原因是因为绑定的字符串键与完全限定类名不匹配。在Laravel的服务容器中,绑定关系是以键值对的形式存储的。当使用`make()`方法时,Laravel会根据传入的字符串键来获取对应的实例。而当使用自动依赖注入时,Laravel会使用反射来检查方法参数的类型。在这种情况下,Laravel将参数类型解析为完全限定类名,而不是绑定时使用的字符串键。因此,当容器中找不到匹配的绑定时,Laravel会创建一个新的实例,而不是使用单例。

使用`::class`语法可以解决这个问题,因为它返回的是完全限定类名。这样,无论是绑定还是引用类时,都能使用同一个字符串键。这样就能正确地引用到绑定的单例实例了。

通过使用`::class`语法,可以避免在Laravel中出现单例绑定多次构建的问题。这种语法的使用只需要几秒钟的时间,但能够解决这个问题,希望对你有帮助。

0
0 Comments

问题出现的原因是因为在代码中多次请求了不同的对象。解决方法是将单例绑定注册为其类名,并将手动调用更改为make($class)。这样,类型提示就可以正常工作了。

具体原因是在代码中的两行:

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

由于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();
    });
}

0