Nette Documentation Preview

syntax
Composing Presenters from Traits
********************************

.[perex]
If we need to implement the same code in multiple presenters (e.g. verification that the user is logged in), it is tempting to place the code in a common ancestor. The second option is to create single-purpose [traits |nette:introduction-to-object-oriented-programming#traits].

The advantage of this solution is that each presenter can use just the traits it actually needs, while multiple inheritance is not possible in PHP.

These traits can take advantage of the fact that all [inject methods|inject-method-attribute#inject methods] are called sequentially when the presenter is created. You just need to make sure that the name of each inject method is unique.

Traits can hang the initialization code into [onStartup or onRender |application:presenters#Events] events.

Examples:

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

The presenter then simply uses these traits:

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


{{sitename: Best Practices}}

Composing Presenters from Traits

If we need to implement the same code in multiple presenters (e.g. verification that the user is logged in), it is tempting to place the code in a common ancestor. The second option is to create single-purpose traits.

The advantage of this solution is that each presenter can use just the traits it actually needs, while multiple inheritance is not possible in PHP.

These traits can take advantage of the fact that all inject methods are called sequentially when the presenter is created. You just need to make sure that the name of each inject method is unique.

Traits can hang the initialization code into onStartup or onRender events.

Examples:

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

The presenter then simply uses these traits:

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