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)?