Métodos de Injeção e Atributos

Neste artigo, vamos nos concentrar em várias formas de passar dependências aos apresentadores na estrutura da Nette. Vamos comparar o método preferido, que é o construtor, com outras opções como inject métodos e atributos.

Também para os apresentadores, a passagem de dependências utilizando o construtor é a forma preferida. Entretanto, se você criar um ancestral comum do qual outros apresentadores herdam (por exemplo, BasePresenter), e este ancestral também tiver dependências, surge um problema, ao qual chamamos de construtor inferno. Isto pode ser contornado usando métodos alternativos, que incluem métodos de injeção e atributos (anotações).

inject*() Métodos

Esta é uma forma de passagem de dependência utilizando setters. Os nomes desses setters começam com o prefixo injetar. Nette DI chama automaticamente tais métodos nomeados imediatamente após criar a instância apresentadora e passa todas as dependências necessárias a eles. Portanto, eles devem ser declarados como públicos.

inject*() métodos podem ser considerados como uma espécie de extensão do construtor em múltiplos métodos. Graças a isso, o BasePresenter pode levar 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;
	}
}

O apresentador pode conter qualquer número de métodos inject*(), e cada um pode ter qualquer número de parâmetros. Isto também é ótimo para casos onde o apresentador é composto de traços, e cada um deles requer sua própria dependência.

Inject Atributos

Esta é uma forma de injeção em propriedades. Basta indicar quais propriedades devem ser injetadas, e a Nette DI passa automaticamente as dependências imediatamente após a criação da instância apresentadora. Para inseri-las, é necessário declará-las como públicas.

As propriedades são marcadas com um atributo: (anteriormente, foi utilizada 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 deste método de passar dependências foi sua forma muito econômica de notação. Entretanto, com a introdução da promoção da propriedade do construtor, o uso do construtor parece mais fácil.

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