Составление презентеров из трейтов

Если вам нужно реализовать одну и ту же функциональность в нескольких презентерах (например, проверку входа пользователя), обычным подходом будет разместить код в общем предке. Другой вариант – создать узконаправленные трейты.

Преимущество трейтов в том, что каждый презентер может подключить только те трейты, которые ему действительно нужны, тем более что множественное наследование в PHP не поддерживается.

Эти трейты могут пользоваться тем, что все методы inject вызываются друг за другом при создании экземпляра презентера. Нужно лишь позаботиться о том, чтобы имя каждого метода inject было уникальным среди всех используемых трейтов и самого презентера.

Трейты могут привязать код инициализации к событиям onStartup или onRender.

Примеры:

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

Презентер затем просто использует эти трейты:

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