Nette DI Container

Nette DI is one of Nette's most interesting libraries. It can generate and automatically update compiled DI containers that are extremely fast and remarkably easy to configure.

The form of services that the DI container should create is usually defined using configuration files in NEON format. The container we manually created in the previous chapter would be written like this:

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

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

The syntax is very concise.

All dependencies declared in the constructors of the ArticleFactory and UserController classes are discovered and passed automatically by Nette DI thanks to so-called autowiring, so there's no need to specify anything in the configuration file. Thus, even if parameters change, you don't need to change anything in the configuration. Nette automatically regenerates the container. You can focus purely on application development.

If we want to pass dependencies using setters, we use the setup section for this.

Nette DI generates PHP code for the container directly. The result is thus a .php file that you can open and examine. This allows you to see exactly how the container functions. You can also debug it in your IDE and step through its execution. And most importantly: the generated PHP code is extremely fast.

Nette DI can also generate factory code based on a provided interface. Therefore, instead of the ArticleFactory class, we only need to create an interface in the application:

interface ArticleFactory
{
	function create(): Article;
}

You can find the full example on GitHub.

Standalone Use

Integrating the Nette DI library into an application is very easy. First, we install it using Composer (because downloading zip files is so outdated):

composer require nette/di

The following code creates an instance of the DI container according to the configuration stored in the config.neon file:

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

The container is generated only once, its code is written to the cache (the __DIR__ . '/temp' directory), and on subsequent requests, it is only loaded from there.

The getService() or getByType() methods are used to create and retrieve services. This is how we create the UserController object:

$userController = $container->getByType(UserController::class);
$userController->doSomething(); // Example usage

During development, it's useful to activate auto-refresh mode, where the container automatically regenerates if any class or configuration file is modified. Just provide true as the second argument in the ContainerLoader constructor.

$loader = new Nette\DI\ContainerLoader(__DIR__ . '/temp', true);

Using with Nette Framework

As we have shown, the use of Nette DI is not restricted to applications built with Nette Framework; you can integrate it anywhere with just three lines of code. However, if you are developing applications using the Nette Framework, the configuration and creation of the container are handled by Bootstrap.

version: 3.x 2.x