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.