Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel: Binding to IoC Container

If you bind a class to the IoC...

App::bind('Thing', function() {
    return new \ThingOne;
});

Then, a ThingOne object will never be instantiated unless you call App::make('Thing'). That is a good thing.

However, if you try to overwrite that binding:

App::bind('Thing', function() {
    return new \ThingOne;
});
App::bind('Thing', function() {
    return new \ThingTwo;
});
App::bind('Thing', function() {
    return new \ThingThree;
});

...then a ThingTwo object and a ThingThree object will be instantiated (and their constructors called) even though you never called App::make('Thing')! That is a bad thing! Why, and how can this be prevented? What purpose does the IoC serve if not to allow us to overwrite bindings so that we can extend packages and whatnot? (That is what I'd like to do: bind classes to the IoC in my packages and then optionally overwrite them when implementing those packages on other projects.)

btw, this happens whether you use bind() or singleton() with no difference.

Thank you so much for any guidance.

like image 323
Leng Avatar asked Oct 01 '22 11:10

Leng


1 Answers

The problem seems to be in Illuminate\Container\Container in the rebound method. That method logically is only called when rebinding so it is not called the first time, but is called the subsequent times. And you can see the instance is created in preparation for rebound callbacks.

/**
 * Fire the "rebound" callbacks for the given abstract type.
 *
 * @param  string  $abstract
 * @return void
 */
protected function rebound($abstract)
{
    $instance = $this->make($abstract);

    foreach ($this->getReboundCallbacks($abstract) as $callback)
    {
        call_user_func($callback, $this, $instance);
    }
}

FractalizeR is right, calling App::offsetUnset('Thing') beforing binding it again does not call the __construct method.

like image 150
dwenaus Avatar answered Oct 09 '22 00:10

dwenaus