I get a bit confused over all the nice things laravel has to offer in terms of the IOC container and facades. Since I'm not an experienced programmer it gets overwhelming to learn.
I was wondering, what is the difference between these two examples:
A facade to 'Foo' and registered in the container via
App::bind()
A facade to 'Foo' and registered in the container via
App::singleton()
In my best understanding Foo::method()
will be rewritten as $app->make['foo']->method()
so in the first example multiple instances of the Foo
class will be created and in the second example, since it's bound via an App::singleton()
, the same instance of Foo
will be returned every time a Method on that object is called.
I'm sorry if the answer to this question is to obvious, but I can't find any confirmation on this matter and nowhere this is clearly explained.
But somewhere I read that Laravel treats classes called via facades always as singletons?
Thereby, I encountered this problem:
I have a demo class normally bound via
An sett up a facade
The class itself looks like this
You told me that if I would use a facade on this class, it would instantiate an object of the class and then call the method on that object.
Butt I tested some more and found this very strange (at least to me) behavior:
If I do
andI shouldn't be able to use Demo::getVals() to retrieve the values I just created, should I? Since every time a facade method is used a new object will be instantiated and how can one object retrieve properties of another object? There should be three different instances but still I'm able to retrieve the properties from those other instances...
It's exactly like that.
A very simple proof is to test out the bevahior. Since the Laravel Application simply extends
Illuminate\Container\Container
, we'll use just the container (in my case I even only added the container as dependency to my composer.json) to test.The result is as expected:
Bind: test vs. test2
Singleton: test2 vs. test2
Might be a dirty proof, but indeed it is one.
All the magic lies in the
Container::make
method. If the binding is registered as shared (which means as singleton), the class instance is returned, otherwise a new instance every time.Source: https://github.com/laravel/framework/blob/4.2/src/Illuminate/Container/Container.php#L442
BTW,
Container::singleton
is the same asContainer::bind
with the third parameter set to true.Facades do work as singleton, even if the underlying binding is not a singleton.
Let's say you have:
and:
Then this will create 2 instances of
FooConcrete
, as usual:But this will create only one instance of
FooConcrete
and reuse it:It is because
resolveFacadeInstance()
stores the resolved instances.There is an exception though. Most of the time the defined
getFacadeAccessor()
returns a string, as shown above, but it can also return an object. Example from theSchema
Facade:In such a case,
resolveFacadeInstance()
doesn't store the instance.So if
getFacadeAccessor()
returns a new instance, each call to the Facade creates a new instance as well.