Nette DI Container

Nette DI Container is one of the most interesting part of framework. It can generate compiled DI containers that are extremely fast and amazingly easy to configure.

Nette DI is a library that provides tools for generating and also automatically updating container classes. We instruct it (usually) using configuration files. The container we manually created in previous section would be written in the configuration NEON format as follows:

		dsn: 'mysql:'
		user: root
		password: '***'

	- Nette\Database\Connection(%db.dsn%, %db.user%, %db.password%)
	- ArticleFactory
	- UserController

The notation is really brief.

All dependencies declared in constructors of ArticleFactory and UserController are automatically detected and passed by Nette DI thanks to the so-called autowiring. So you can concentrate on development.

If you want to pass dependencies using a setter, we can add a setup section to the service definition.

Nette DI will actually generate the PHP code for the container. It is therefore extremely fast, the programmer knows exactly what he is doing and can even step it. A container can be tens of thousands of lines long for large applications, and maintaining something like this manually would probably not even be possible anymore.

Nette DI can also generate factory code based on the interface. So instead of a class ArticleFactory, you would just need to create an interface:

interface ArticleFactory
	function create(): Article;

You can find the full example on GitHub.

Using it without a framework

Utilization of Nette DI in an application is very easy. First we install it with Composer (because downloading zip files is so outdated):

composer require nette/di

We save the above configuration in a file config.neon and create a container using class Nette\DI\ContainerLoader:

$loader = new Nette\DI\ContainerLoader(__DIR__ . '/temp');
$class = $loader->load(function($compiler) {
	$compiler->loadConfig(__DIR__ . '/config.neon');
$container = new $class;

and then let it create an object for example Nette\Database\Connection:

$database = $container->getByType(Nette\Database\Connection::class);

But back to ContainerLoader for a moment. That notation is subject to one thing: speed. The container is generated once, its code is written to the cache (directory __DIR__ . '/temp'), and on subsequent requests it is only retrieved from there. Therefore, the configuration retrieval is placed in the closure in method $loader->load().

During development, it is useful to enable auto-refresh mode, where the container is automatically re-generated if any class or configuration file is changed. Just provide true as the second argument in the constructor ContainerLoader.

As you can see, the use of Nette DI is definitely not limited to applications written in Nette, you can deploy it anywhere with just 3 lines of code.

Using it with the Nette Framework

If you are developing applications in Nette, the configuration and creation of the container is handled by Bootstrap.