nette/bootstrap — pull request #31 by VasekPurchart (2014-12-27 16:05:32+00:00)
Title: Configurator: add service instances to be injected to container

When developing extensions I've encountered this problem several times: how to add an instance of a service, which you need to use before the container is created (and the same instance must available for extensions in DIC later.)

There are workarounds for this problem, you can for example define the service with a "dummy" and then "as soon as possible" add the correct instance, such as this example with RobotLoader.

``` php
$configurator = new Configurator();
$robotLoader = $configurator->createRobotLoader();

// register extensions

$container = $configurator->createContainer();
$container->addService('robotLoader', $robotLoader);
```

This usually works, but as most workaround has several problems - if something, that requires a RobotLoader instance, is called before the `$robotLoader` instance is registered, new (probably misconfigured) service instance is used. This problem would probably occur most of the times due to extensions, which generate code for the `Container::initialize` method, because this would be called between these two actions and AFAIK there is no way to solve this.

This situation with RobotLoader is only an example, but I think this is a general issue, that's why I am proposing this `Configurator::addServices` possibility. The way I see it - the usecase is similar to `Configurator::addParameters` (hence the similar name). These are parameters that we need to use even before the Container is created, this is the same for services. The only difference is that parameters are then statically generated to container, which is IMHO not suitable for service instances. So instances are added after the creation of the whole Container, but before the `initialize` method.

If there are some services, that require such a dependency e.g. RobotLodaer, the trick with defining the "dummy" should still work like this:
``` yml
services:
robotLoader:
class: Nette\Loaders\RobotLoader
```
``` php
$configurator = new Configurator();
$robotLoader = $configurator->createRobotLoader();
$configurator->addServices(array(
'robotLoader', $robotLoader,
));

$container = $configurator->createContainer();
```
Since the first code which can work with the Container is in the `Container::initialize()` method, this should become really consistent.

What do you think about this?
Do you see any potential problems?
Do you have another solution to the problem I outlined above? Right now I am in an deadlock with my extensions because of this issue :(

cc @fprochazka @Vrtak-CZ