Nette Documentation Preview

syntax
Métodos e atributos inject
**************************

.[perex]
Neste artigo, focaremos nas diferentes maneiras de passar dependências para presenters no framework Nette. Compararemos a forma preferida, que é o construtor, com outras opções, como métodos e atributos `inject`.

Também para presenters, passar dependências usando o [construtor |dependency-injection:passing-dependencies#Passagem pelo construtor] é o caminho preferido. No entanto, se você criar um ancestral comum do qual outros presenters herdam (por exemplo, `BasePresenter`), e este ancestral também tiver dependências, ocorrerá um problema que chamamos de [constructor hell |dependency-injection:passing-dependencies#Constructor hell]. Isso pode ser contornado usando caminhos alternativos, que são os métodos e atributos (anotações) `inject`.


Métodos `inject*()`
===================

É uma forma de passar dependências por [setter |dependency-injection:passing-dependencies#Passagem por setter]. O nome desses setters começa com o prefixo `inject`. O Nette DI chama automaticamente métodos com esse nome logo após a criação da instância do presenter e passa a eles todas as dependências necessárias. Portanto, eles devem ser declarados como `public`.

Os métodos `inject*()` podem ser considerados como uma extensão do construtor em vários métodos. Graças a isso, o `BasePresenter` pode receber dependências através de outro método e deixar o construtor livre para seus descendentes:

```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;
	}
}
```

Um presenter pode conter qualquer número de métodos `inject*()` e cada um pode ter qualquer número de parâmetros. Eles também são ótimos em casos onde o presenter é [composto por traits |presenter-traits] e cada um deles requer sua própria dependência.


Atributos `Inject`
==================

É uma forma de [injeção na propriedade |dependency-injection:passing-dependencies#Configuração de propriedade]. Basta marcar em quais propriedades injetar, e o Nette DI passa automaticamente as dependências logo após a criação da instância do presenter. Para poder inseri-las, é necessário declará-las como `public`.

Marcamos as propriedades com um atributo: (anteriormente, usava-se a anotação `/** @inject */`)

```php
use Nette\DI\Attributes\Inject;  // esta linha é importante

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

A vantagem dessa forma de passar dependências era a forma de escrita muito concisa. No entanto, com a chegada da [promoção de propriedades do construtor |https://blog.nette.org/pt/php-8-0-complete-overview-of-news#toc-constructor-property-promotion], parece mais fácil usar o construtor.

Por outro lado, essa forma sofre das mesmas desvantagens que a passagem de dependências para propriedades em geral: não temos controle sobre as alterações na variável e, ao mesmo tempo, a variável se torna parte da interface pública da classe, o que é indesejável.


{{sitename: Best Practices}}

Métodos e atributos inject

Neste artigo, focaremos nas diferentes maneiras de passar dependências para presenters no framework Nette. Compararemos a forma preferida, que é o construtor, com outras opções, como métodos e atributos inject.

Também para presenters, passar dependências usando o construtor é o caminho preferido. No entanto, se você criar um ancestral comum do qual outros presenters herdam (por exemplo, BasePresenter), e este ancestral também tiver dependências, ocorrerá um problema que chamamos de constructor hell. Isso pode ser contornado usando caminhos alternativos, que são os métodos e atributos (anotações) inject.

Métodos inject*()

É uma forma de passar dependências por setter. O nome desses setters começa com o prefixo inject. O Nette DI chama automaticamente métodos com esse nome logo após a criação da instância do presenter e passa a eles todas as dependências necessárias. Portanto, eles devem ser declarados como public.

Os métodos inject*() podem ser considerados como uma extensão do construtor em vários métodos. Graças a isso, o BasePresenter pode receber dependências através de outro método e deixar o construtor livre para seus descendentes:

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;
	}
}

Um presenter pode conter qualquer número de métodos inject*() e cada um pode ter qualquer número de parâmetros. Eles também são ótimos em casos onde o presenter é composto por traits e cada um deles requer sua própria dependência.

Atributos Inject

É uma forma de injeção na propriedade. Basta marcar em quais propriedades injetar, e o Nette DI passa automaticamente as dependências logo após a criação da instância do presenter. Para poder inseri-las, é necessário declará-las como public.

Marcamos as propriedades com um atributo: (anteriormente, usava-se a anotação /** @inject */)

use Nette\DI\Attributes\Inject;  // esta linha é importante

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

A vantagem dessa forma de passar dependências era a forma de escrita muito concisa. No entanto, com a chegada da promoção de propriedades do construtor, parece mais fácil usar o construtor.

Por outro lado, essa forma sofre das mesmas desvantagens que a passagem de dependências para propriedades em geral: não temos controle sobre as alterações na variável e, ao mesmo tempo, a variável se torna parte da interface pública da classe, o que é indesejável.