I have a follow-up question to the one discussed here:
Laravel core method confusion
I am in the same situation as driechel (author of question above) has been before, currently getting used to Laravel 4 FW and examining the core. Although a precise answer has been given I still don't understand the logic and what is happening under the hood. So I would very much appreciate a further explanation.
I know this might be a duplicate but since I cannot post comments yet I'll give it a shot with a new question. Hope it' ok this way.
I have been looking at this from another angle starting at this article:
http://blog.joynag.net/2013/05/facades-in-laravel-4-and-static-methods-resolution/
When examining the call File:get()
I finally end up at the Container class' share function which is called with this actual parameter share(function() { return new Filesystem; }
.
What I just can't figure out is the use of $container
. Especially at the second occurence within the closure:
$object = $closure($container);
Could you please clarify this again? Why is $container
passed as a parameter here and what is actually contained in it? As far as I understand $closure
at that point holds and executes function() { return new Filesystem; }
which has no input parameter.
I am lost. Studied this and the PHP anonymous functions/closures now for two days straight and still can't figure it out. I neither understand the syntax of $closure($container)
here nor the logic.
For reference, this is the share
method @ v4.0.5.
So, what's happening here. I'll explain it in a couple of steps.
Calling The Share Method
As you pointed out this method is called from service providers. So, the FilesystemServiceProvider
calls this method which looks something like this:
$this->app['files'] = $this->app->share(function() { return new Filesystem; });
It's assigning the return value of this share
method to a binding in the container. In a nutshell, that return value will be the new Filesystem
instance that is returned in the closure.
So What Does Share Do?
The share
method is just another way of defining a singleton in IoC container. All this can be a bit intimidating at first. Basically, Laravel itself is an IoC container. All the classes are bound as instances on the container. Sometimes these instances should be the same instance on every call.
If you take a look at the referencing method above on GitHub, you'll notice that inside the closure a static variable is defined. It then checks if that variable is null, and if it is it resolves the closure (this is the closure that returns our new Filesystem
instance). Then it simply returns the variable.
Now, the next time you use File::get()
it doesn't need to instantiate the Filesystem
class again, because it's already been instantiated and stored in the static $object
variable. So it simply returns the same object to you.
So! Really, you could replace the $this->app['files']
line with this, and it would still work.
$this->app->instance('files', new Filesystem);
99% of services actually use the share
method though because working inside a closure allows objects to be instantiated with more complex dependencies.
Hope this helps.