driechel
driechel

Reputation: 3453

Laravel core method confusion

I have been digging in the core of Laravel because I would like to understand how it works. But I come up with a method that I just cannot wrap my head around even after 3 days. In start.php the app is binded to itself. So far so good. But when I check the $app->share method I am lost.

    public function share(Closure $closure)
{
    return function($container) use ($closure)
    {

        // We'll simply declare a static variable within the Closures and if
        // it has not been set we'll execute the given Closure to resolve
        // the value and return it back to the consumers of the method.
        static $object;
        if (is_null($object))
        {
            $object = $closure($container);
        }

        return $object;
    };
}

This method returns an anonymous function which when executed returns an instance of the app. Do I see that right? Why is this? Why do you want to return a closure and not just the instance. This seems like a strange way, but I am quite sure that there is a reason ;) ??

UPDATE The line in start.php:

$app['app'] = $app->share(function($app) { return $app; });

So I would think that $app['app'] is a closure object. However if I do get_class the class is Illuminate\Foundation\Application . Furthermore there is also no way to execute it as $app'app' will not work obviously.

Upvotes: 4

Views: 396

Answers (1)

Phill Sparks
Phill Sparks

Reputation: 20899

$app is no normal array, it is actually an instance of Illuminate\Foundation\Application1, an extension of Illuminate\Container\Container2, which implements ArrayAccess. But you know this already, as that's where the share() method lives.

The container binds keys to closures, when the keys are accessed the value is fetched from memory or, on first access, the bound closure is called and the resulting value is returned. When a key is set on the container it is wrapped in a closure unless it is already a closure.

This provides a consistent internal interface for the container, so that the code is not constantly type checking its contents. It will also only load the references you actually use are into memory - it is thought that the footprint of a closure is lighter than that of a fully loaded class instance. But once loaded, you get the benefit of working with the same instance for the rest of the request.

Why the app is not registered on the container using instance() I don't know though - perhaps it produces recursive references in trace and dump output.

Upvotes: 3

Related Questions