Composição dos apresentadores a partir de traços

Se precisarmos implementar o mesmo código em vários apresentadores (por exemplo, verificação de que o usuário está conectado), é tentador colocar o código em um ancestral comum. A segunda opção é criar características de finalidade única.

A vantagem desta solução é que cada apresentador pode usar apenas os traços de que realmente precisa, enquanto a herança múltipla não é possível em PHP.

Estas características podem aproveitar o fato de que todos os métodos de injeção são chamados sequencialmente quando o apresentador é criado. Basta ter certeza de que o nome de cada método de injeção é único.

As características podem pendurar o código de inicialização em eventos onStartup ou onRender.

Exemplos:

trait RequireLoggedUser
{
	public function injectRequireLoggedUser(): void
	{
		$this->onStartup[] = function () {
			if (!$this->getUser()->isLoggedIn()) {
				$this->redirect('Sign:in', $this->storeRequest());
			}
		};
	}
}

trait StandardTemplateFilters
{
	public function injectStandardTemplateFilters(TemplateBuilder $builder): void
	{
		$this->onRender[] = function () use ($builder) {
			$builder->setupTemplate($this->template);
		};
	}
}

O apresentador então simplesmente usa estes traços:

class ArticlePresenter extends Nette\Application\UI\Presenter
{
	use StandardTemplateFilters;
	use RequireLoggedUser;
}