トレイトによるプレゼンターの構成

同じ機能を複数のプレゼンターで実装する必要がある場合(ユーザーのログイン確認など)、共通の祖先にコードを置くのがよくあるやり方です。もうひとつの選択肢が、目的をひとつに絞ったトレイトを作ることです。

トレイトを使う利点は、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;
}