Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel 4 - Container class: share function & closure logic

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.

like image 476
sese Avatar asked Jun 25 '13 11:06

sese


1 Answers

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.

like image 142
Jason Lewis Avatar answered Oct 03 '22 19:10

Jason Lewis