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.
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:
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.
It's the facade treating everything as a singleton
?
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)
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 servicesRe: #7, here's the definition of
singleton
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 yourregister
method isn't called for some reason,make
will still instantiate an object with your global classData
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 callSo, a facade uses
$app[$name];
to grab a service from the container. This isArrayAccess
, so if we look at the definition ofoffsetGet
We see
ArrayAccess
wraps a call tomake
. 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.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 theFacade
class.