Luuk Van Dongen Luuk Van Dongen - 3 months ago 94
PHP Question

Laravel: Difference App::bind and App::singleton

I get a bit confused over all the nice things laravel has to offer in terms of the IOC container and facades. Since I'm not an experienced programmer it gets overwhelming to learn.

I was wondering, what is the difference between these two examples:


  1. A facade to 'Foo' and registered in the container via
    App::bind()

  2. A facade to 'Foo' and registered in the container via
    App::singleton()



In my best understanding
Foo::method()
will be rewritten as
$app->make['foo']->method()
so in the first example multiple instances of the
Foo
class will be created and in the second example, since it's bound via an
App::singleton()
, the same instance of
Foo
will be returned every time a Method on that object is called.

I'm sorry if the answer to this question is to obvious, but I can't find any confirmation on this matter and nowhere this is clearly explained.

Answer

It's exactly like that.

A very simple proof is to test out the bevahior. Since the Laravel Application simply extends Illuminate\Container\Container, we'll use just the container (in my case I even only added the container as dependency to my composer.json) to test.

require __DIR__ . '/vendor/autoload.php';

class FirstClass
{
    public $value;
}

class SecondClass
{
    public $value;
}

// Test bind()
$container = new Illuminate\Container\Container();

$container->bind('FirstClass');

$instance = $container->make('FirstClass');
$instance->value = 'test';

$instance2 = $container->make('FirstClass');
$instance2->value = 'test2';

echo "Bind: $instance->value vs. $instance2->value\n";

// Test singleton()
$container->singleton('SecondClass');

$instance = $container->make('SecondClass');
$instance->value = 'test';

$instance2 = $container->make('SecondClass');
$instance2->value = 'test2'; // <--- also changes $instance->value

echo "Singleton: $instance->value vs. $instance2->value\n";

The result is as expected:

Bind: test vs. test2

Singleton: test2 vs. test2

Might be a dirty proof, but indeed it is one.

All the magic lies in the Container::make method. If the binding is registered as shared (which means as singleton), the class instance is returned, otherwise a new instance every time.

Source: https://github.com/laravel/framework/blob/4.2/src/Illuminate/Container/Container.php#L442

BTW, Container::singleton is the same as Container::bind with the third parameter set to true.