You are browsing the unmaintained documentation for old Nette 2.1. See documentation for current Nette.

DI: Creating Extensions

Configurator does not generate the code itself, that is the task of Nette\DI\Compiler and Nette\DI\ContainerBuilder classes. First configuration files are loaded and passed to Compiler. Add your own extension to Compiler via config.neon:

	blog: MyBlogExtension

Each Compiler extension must extend Nette\DI\CompilerExtension and can implement three different methods that are called successively during the Container compilation.


This method is called first and loads additional configuration files, creates methods using Nette\DI\ContainerBuilder and most importantly processes the application's configuration.

Config can contain a section bearing the same name as your extension. Using the last example, following lines can appear in your config file:

blog: # same name as your extension
	postsPerPage: 10
	comments: FALSE

Use getConfig() method in the extension to list its configuration.

class MyBlogExtension extends Nette\DI\CompilerExtension
	public function loadConfiguration()
		$config = $this->getConfig();
		// array(2) [ 'postsPerPage' => 10, 'comments' => FALSE ]

Honoring the convention over configuration principle we can set default values and be able to use the application without explicitly setting anything. First argument of getConfig() accepts an array of default values, into which the config section (as mentioned above) will be merged.

class MyBlogExtension extends Nette\DI\CompilerExtension
	public $defaults = array(
		'postsPerPage' => 5,
		'comments' => TRUE

	public function loadConfiguration()
		$config = $this->getConfig($this->defaults);

Now we have the configuration in the $config array and can use it while creating the services. ContainerBuilder class allows you to use the same way of service description as NEON used in the configuration files.

$builder = $this->getContainerBuilder();

Create blog_articles service representing a model for handling and loading articles.

Convention is to prefix services by their name to avoid conflicts. Using prefix() method we can then access the service via $container->getService('blog.articles).

	->setFactory('MyBlog\ArticlesModel', array('@connection'))
	->addSetup('setLogger', array('@logger'));

Loading additional configurations

If you prefer configuration files over extensions, you can move some of the definitions into separate configuration file.

		factory: MyBlog\ArticlesModel(@connection)

		factory: MyBlog\CommentsModel(@connection, @blog_articles)

		factory: MyBlog\Components\ArticlesList(@blog_articles)

Load the file and set additional services

public function loadConfiguration()
	$config = $this->getConfig($this->defaults);
	$builder = $this->getContainerBuilder();

	// load additional config file for this extension
	$this->compiler->parseServices($builder, $this->loadFromFile(__DIR__ . '/blog.neon'));

	// set a number of articles per page in the component
		->addSetup('setPostsPerPage', $config['postsPerPage']);

	// optional disabling of commenting
	if (!$config['comments']) {


In beforeCompile phase we should not add any more services, however you can modify already existing ones or add relations between services (for example using tags).


In this phase the Container instance is already generated and contains all service methods and is ready to be stored into cache. Thanks to Nette\PhpGenerator\ClassType you can add your own code to the container to modify the service generation.

To inspire yourself take a look at Nette Framework's initialize method, which Nette adds to process some of the user settings. This method is always called after instantiation of the container.

Here is a piece of code of initialize where Nette adds a session start and autorun of services marked with run tag.

public function afterCompile(Nette\PhpGenerator\ClassType $class)
	$container = $this->getContainerBuilder();
	$config = $this->getConfig($this->defaults);

	// initialize method
	$initialize = $class->methods['initialize'];

	// automatic session start
	if ($config['session']['autoStart']) {

	// services with run tag must be run after instantition of the container
	foreach ($container->findByTag('run') as $name => $foo) {
		$initialize->addBody('$this->getService(?);', array($name));

Related blog posts