Nette DI Container

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

The services to be created by a DI container are usually defined using configuration files in NEON format. The container we manually created in previous section would be written as follows:

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

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

The notation is really brief.

All dependencies declared in the constructors of the ArticleFactory and UserController classes are found and passed by Nette DI itself thanks to the so-called autowiring, so there is no need to specify anything in the configuration file. So even if the parameters change, you don't need to change anything in the configuration. Nette will automatically regenerate the container. You can concentrate there purely on application development.

If you want to pass dependencies using setters, use the setup section to do so.

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

Nette DI can also generate factory code based on the supplied 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

Utilization the Nette DI library in an application is very easy. First we install it with 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 read from there.

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

$database = $container->getByType(UserController::class);
$database->query('...');

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

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

Using It with the Nette Framework

As we have shown, the use of Nette DI is not limited to applications written in the Nette Framework, you can deploy it anywhere with just 3 lines of code. However, if you are developing applications in the Nette Framework, the configuration and creation of the container is handled by Bootstrap.