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.