Nette Documentation Preview

syntax
Inject Methods and Attributes
*****************************

.[perex]
Using specific examples, we will look at the possibilities of passing dependencies to presenters and explain the `inject` methods and attributes/annotations.


`inject*()` Methods
===================

In presenter, as in any other code, the preferred way of passing dependencies is by using [constructor |dependency-injection:passing-dependencies#Constructor Injection]. However, if the presenter inherits from a common ancestor (e.g. `BasePresenter`), it is better to use the methods of `inject*()` in that ancestor. It is a special case of a setter, where the method starts with a prefix `inject`. This is because we keep the constructor free for descendants:

```php
abstract class BasePresenter extends Nette\Application\UI\Presenter
{
	private Foo $foo;

	public function injectBase(Foo $foo): void
	{
		$this->foo = $foo;
	}
}

class MyPresenter extends BasePresenter
{
	private Bar $bar;

	public function __construct(Bar $bar)
	{
		$this->bar = $bar;
	}
}
```

The basic difference from a setter is that Nette DI automatically calls methods named this way in presenters as soon as the instance is created, passing all required dependencies to them. A presenter can contain multiple methods `inject*()` and each method can have any number of parameters.

If we passed dependencies to ancestors through their constructors, we would have to get their dependencies in all descendants and pass them to `parent::__construct()`, which complicates the code:

```php
abstract class BasePresenter extends Nette\Application\UI\Presenter
{
	private Foo $foo;

	public function __construct(Foo $foo)
	{
		$this->foo = $foo;
	}
}

class MyPresenter extends BasePresenter
{
	private Bar $bar;

	public function __construct(Foo $foo, Bar $bar)
	{
		parent::__construct($foo); // this is a complication
		$this->bar = $bar;
	}
}
```

The `inject*()` methods are also useful in cases where the presenter is [composed of traits |presenter-traits] and each of them requires its own dependency.

It is also possible to use annotation `@inject`, but it is important to keep in mind that encapsulation breaks.


`Inject` Annotations
====================

This is an automatic passing of the dependency to the presenter's public member variable, which is annotated with `@inject` in the documentation comment. The type can also be specified in the documentation comment if you are using PHP lower than 7.4.

```php
class MyPresenter extends Nette\Application\UI\Presenter
{
	/** @inject */
	public Cache $cache;
}
```

Since PHP 8.0, a property can be marked with an attribute `Inject`:

```php
use Nette\DI\Attributes\Inject;

class MyPresenter extends Nette\Application\UI\Presenter
{
	#[Inject]
	public Cache $cache;
}
```

Again, Nette DI will automatically pass dependencies to properties annotated in this way in the presenter as soon as the instance is created.

This method has the same shortcomings as passing dependencies to a public property. It is used in presenter because it does not complicate the code and requires only a minimum of typing.


{{sitename: Best Practices}}

Inject Methods and Attributes

Using specific examples, we will look at the possibilities of passing dependencies to presenters and explain the inject methods and attributes/annotations.

inject*() Methods

In presenter, as in any other code, the preferred way of passing dependencies is by using constructor. However, if the presenter inherits from a common ancestor (e.g. BasePresenter), it is better to use the methods of inject*() in that ancestor. It is a special case of a setter, where the method starts with a prefix inject. This is because we keep the constructor free for descendants:

abstract class BasePresenter extends Nette\Application\UI\Presenter
{
	private Foo $foo;

	public function injectBase(Foo $foo): void
	{
		$this->foo = $foo;
	}
}

class MyPresenter extends BasePresenter
{
	private Bar $bar;

	public function __construct(Bar $bar)
	{
		$this->bar = $bar;
	}
}

The basic difference from a setter is that Nette DI automatically calls methods named this way in presenters as soon as the instance is created, passing all required dependencies to them. A presenter can contain multiple methods inject*() and each method can have any number of parameters.

If we passed dependencies to ancestors through their constructors, we would have to get their dependencies in all descendants and pass them to parent::__construct(), which complicates the code:

abstract class BasePresenter extends Nette\Application\UI\Presenter
{
	private Foo $foo;

	public function __construct(Foo $foo)
	{
		$this->foo = $foo;
	}
}

class MyPresenter extends BasePresenter
{
	private Bar $bar;

	public function __construct(Foo $foo, Bar $bar)
	{
		parent::__construct($foo); // this is a complication
		$this->bar = $bar;
	}
}

The inject*() methods are also useful in cases where the presenter is composed of traits and each of them requires its own dependency.

It is also possible to use annotation @inject, but it is important to keep in mind that encapsulation breaks.

Inject Annotations

This is an automatic passing of the dependency to the presenter's public member variable, which is annotated with @inject in the documentation comment. The type can also be specified in the documentation comment if you are using PHP lower than 7.4.

class MyPresenter extends Nette\Application\UI\Presenter
{
	/** @inject */
	public Cache $cache;
}

Since PHP 8.0, a property can be marked with an attribute Inject:

use Nette\DI\Attributes\Inject;

class MyPresenter extends Nette\Application\UI\Presenter
{
	#[Inject]
	public Cache $cache;
}

Again, Nette DI will automatically pass dependencies to properties annotated in this way in the presenter as soon as the instance is created.

This method has the same shortcomings as passing dependencies to a public property. It is used in presenter because it does not complicate the code and requires only a minimum of typing.