What's the difference between App::singleton and bindShared?

ioc-container, laravel, laravel-4, php, singleton

Solution

I've been wondering the same thing. I don't know the motivations behind this, but I can speak to a few differences.

Here is the definition of the two methods from Laravel 4.2:

public function singleton($abstract, $concrete = null)
{
    $this->bind($abstract, $concrete, true);
}

public function bindShared($abstract, Closure $closure)
{ 
    $this->bind($abstract, $this->share($closure), true);
}

Similarities:

- Both methods call `bind()` under the hood.

- Both methods pass `true` to the 3rd parameter of `bind()`, which signifies that this is a shared object.

- In both cases, because this is a shared object, a call to `isShared($abstract)` will return true.

- In both cases, because this is a shared object, a call to `make($abstract)` will return only the first instance.

Differences:

- `singleton()` will accept a `Closure` or a `string`. `bindShared()` will only accept a `Closure`, not a `string`.

- `bindShared()`, in addition to binding the object into the IOC container as a shared object, takes the additional step of wrapping the passed `Closure` in a `share`'d `Closure`, which prevents the passed `Closure` from being executed more than once. At first glance, this appears to be a double assurance that the object will be treated as a singleton. I can only guess why this might be desirable.

- `bindShared()` is called 87 times inside the framework. `singleton()` is called 0 times.

Problem

The Laravel docs indicate that the appropriate way to bind a singleton is with the `App::singleton()` method, but internally Laravel will use the `bindShared()` method (for example, in `TranslationServiceProvider`). I assume that the documented approach is preferred, but is there a functional difference? If not, is there any reason for having two approaches (beyond maybe historical accident)?

Original source