Laravel 4’s IoC container is the part worth keeping

Most of what gets written about Laravel 4 is about the parts you see — routes, Blade, Eloquent. The piece that changed how I write plain PHP is underneath all of it: a container that reads a constructor’s type hints and builds the object graph, with no configuration for the cases where there is nothing to decide.

// app/start/global.php, or a service provider
App::bind('CatalogueContractsPriceSource', 'CatalogueFeedFeedPriceSource');

App::singleton('CatalogueImportRunner', function ($app) {
    return new CatalogueImportRunner(
        $app->make('CatalogueContractsPriceSource'),
        Config::get('import.batch_size')
    );
});

class ImportController extends BaseController
{
    protected $runner;

    // nothing to register for this: the type hint is the wiring
    public function __construct(CatalogueImportRunner $runner)
    {
        $this->runner = $runner;
    }
}

Only two kinds of thing need a binding: an interface, because reflection cannot guess which implementation you meant, and anything whose construction needs a value rather than another object. Everything else resolves from the signature, which means the dependencies of a class are declared in the one place a reader is already looking. That is available outside the framework — illuminate/container is its own package and works in an application with no Laravel in it. What I would not take is the facades: Config::get() in the closure above is a static call to a global, and a class doing that has hidden the dependency the constructor was meant to expose. The container’s cost is reflection on every unregistered resolution, so anything constructed repeatedly per request wants singleton rather than bind.