phplaravelioc-containerlaravel-facade

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.

Is my assumption correct?


Solution

  • It's exactly like that.

    A very simple proof is to test out the behavior. 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 a 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.