Laravel app->bind 和 app->singleton 之间的区别?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25797594/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Laravel Difference `between app->bind` and `app->singleton`?
提问by Rob
I've been trying to figure out what the difference between app->bind
and app->singleton
are when setting up a service provider in Laravel. I was under the impression that if I register an singleton
it would return the same instance of the object each time it was called vs bind
which would be a new instance.
我一直试图弄清楚在 Laravel 中设置服务提供程序时app->bind
和之间的区别app->singleton
。我的印象是,如果我注册一个,singleton
它会在每次调用它时返回对象的相同实例,而bind
这将是一个新实例。
Here is simple example:
这是一个简单的例子:
Facade:
正面:
use Illuminate\Support\Facades\Facade;
class DataFacade extends Facade
{
protected static function getFacadeAccessor() {
return 'Data';
}
}
ServiceProvider:
服务提供者:
use Illuminate\Support\ServiceProvider;
class DataServiceProvider extends ServiceProvider
{
public function register() {
$this->app->singleton('Data', function() {
return new Data;
});
}
}
Class:
班级:
class Data
{
public $data = [];
public function get($key)
{
return isset($this->data[$key]) ? $this->data[$key] : null;
}
public function set($key, $val)
{
$this->data[$key] = $val;
}
}
If we do something like:
如果我们做这样的事情:
$instance = App::make('Data');
$instance->set('foo', 'foo');
$instance2 = App::make('Data');
echo $instance->get('foo');
echo $instance2->get('foo');
And run that we will see the appropriate behavior between bind
and singleton
with foo
being printed out once and then twice respectively. However if we run it through the facade like so:
然后运行,我们将看到bind
和之间的适当行为singleton
,foo
分别打印一次和两次。但是,如果我们像这样通过门面运行它:
Data::set('test', 'test');
Data::set('cheese', 'cheese');
When it's a singleton I would expect both test
and cheese
to be available and when it's a bind
I'm not sure what I would expect to be available via the facade, but it seems like there is no difference.
当它是单身时,我希望test
和cheese
都可用,而当它是一个时,bind
我不确定我希望通过外观获得什么,但似乎没有区别。
It's the facade treating everything as a singleton
?
这是外观将一切视为singleton
?
回答by Alan Storm
Your question is a little confusing and doesn't have all the information for someone to answer, but it's a confusing topic, so don't feel bad. Here's a rundown that may help you better understand, and ask the question you wanted to ask (also, I'm newish to Laravel, so I may be off base with these)
您的问题有点令人困惑,并且没有可供某人回答的所有信息,但这是一个令人困惑的话题,所以不要难过。这是一个纲要,可以帮助您更好地理解,并提出您想问的问题(另外,我是 Laravel 的新手,所以我可能对这些不了解)
The
make
method is used to instantiate objects. When you sayApp::make('Data')
you're telling Laravel to instantiate an object from the classData
.There's a caveat to number 1. If you call
make
and have already bound the stringData
to something in the service container, Laravel will return the service instead. This may mean Laravel instantiates a new service object, or it may mean Laravel returns a service singletonWhether or not Laravel returns a singleton or an instance for a service depends on how the service was bound
The
make
method doesn't bind anythingYou bind services with the application object's
bind
method, defined on the container class with the following method prototypepublic function bind($abstract, $concrete = null, $shared = false)
See that third
$shared
parameter? If that's true your service will return a singleton. If it's false your service will return instances.The application object's
singleton
method is a method for binding services
该
make
方法用于实例化对象。当你说App::make('Data')
你告诉 Laravel 从 class 实例化一个对象时Data
。第 1 条有一个警告。如果您调用
make
并且已经将字符串绑定Data
到服务容器中的某些内容,Laravel 将改为返回服务。这可能意味着 Laravel 实例化了一个新的服务对象,也可能意味着 Laravel 返回了一个服务单例Laravel 是否为服务返回单例或实例取决于服务是如何绑定的
该
make
方法不绑定任何东西您使用应用程序对象的
bind
方法绑定服务,在容器类上使用以下方法原型定义public function bind($abstract, $concrete = null, $shared = false)
看到第三个
$shared
参数了吗?如果这是真的,您的服务将返回一个单身人士。如果它是假的,您的服务将返回实例。应用程序对象的
singleton
方法是绑定服务的方法
Re: #7, here's the definition of singleton
回复:#7,这是定义 singleton
#File: vendor/laravel/framework/src/Illuminate/Container/Container.php
public function singleton($abstract, $concrete = null)
{
$this->bind($abstract, $concrete, true);
}
In your examples above you're binding the service Data
into the container. Using a leading case service name is going to cause problems -- data
would be a better choice. If your register
method isn't called for some reason, make
will still instantiate an object with your global class Data
在上面的示例中,您将服务绑定Data
到容器中。使用领先的案例服务名称会导致问题——data
这将是一个更好的选择。如果您的register
方法由于某种原因未被调用,make
仍将使用您的全局类实例化一个对象Data
Regarding your Facade -- a Facade is an extra layer of instance/singleton-ness. Here's the method where the facade class uses the string from getFacadeAccessor
to return an object from a static call
关于你的门面——门面是一个额外的实例/单一层。这是外观类使用字符串 fromgetFacadeAccessor
从静态调用返回对象的方法
#File: vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php
protected static function resolveFacadeInstance($name)
{
if (is_object($name)) return $name;
if (isset(static::$resolvedInstance[$name]))
{
return static::$resolvedInstance[$name];
}
return static::$resolvedInstance[$name] = static::$app[$name];
}
So, a facade uses $app[$name];
to grab a service from the container. This is ArrayAccess
, so if we look at the definition of offsetGet
因此,外观用于$app[$name];
从容器中获取服务。这是ArrayAccess
,所以如果我们看一下offsetGet
public function offsetGet($key)
{
return $this->make($key);
}
We see ArrayAccess
wraps a call to make
. This means if you have no bound service, facade access will instantiate an object. If you have the service bound as a singleton/shared service, facade access will return that singleton. If you have the service bound as not a singleton/shared service, facade access will instantiate a new object.
我们看到ArrayAccess
包装了对 的调用make
。这意味着如果您没有绑定服务,门面访问将实例化一个对象。如果您将服务绑定为单例/共享服务,门面访问将返回该单例。如果您将服务绑定为不是单例/共享服务,门面访问将实例化一个新对象。
HOWEVER, the Facade itself will store any object it instantiates inside static::$resolvedInstance
, and future calls to the facade will return this same instance. This means Facade access introduces a second singleton implementation. A service bound as a singleton will be stored on the application object, a service accessed via a facade will be stored as a singleton on the Facade
class.
然而, Facade 本身将存储它在其中实例化的任何对象static::$resolvedInstance
,并且对 Facade 的未来调用将返回相同的实例。这意味着 Facade 访问引入了第二个单例实现。绑定为单例的服务将存储在应用程序对象中,通过外观访问的服务将作为单例存储在Facade
类中。