Presenters
Presenters help you organize view layer (presentation) logic for the objects. Logic in the presenter should only be for display purposes.
An important secondary purpose for presenters is to map the decorated object's API in a clean way for views. This is why the __get method has logic in it which you'll read about further down.
Basic Usage
The \Robbo\Presenter\PresentableInterface interface tells the Streams Platform that the class is presentable and has a getPresenter method. By default getPresenter return an instance of \Anomaly\Streams\Platform\Support\Presenter or the nearest presenter to the class.
public function newPresenter()
{
return new Presenter($this);
}
Presenter::getObject()
The getObject returns the decorated object instance.
Returns: mixed
Example
$presenter->getObject();
Twig
{{ presenter.getObject() }}
Presenter::__get()
The __get magic method will look for the following available methods in order from top to bottom and return the first matching scenario:
Check the presenter for a method where the method is the camel case of the {attribute_name}.
$presenter->display_name; // Returns: $presenter->displayName();
{{ presenter.display_name }} // Returns: {{ presenter.displayName() }}
Check the presenter for a getter method where the method is the camel case of get_{attribute_name}.
$presenter->display_name; // Returns: $presenter->getDisplayName();
{{ presenter.display_name }} // Returns: {{ presenter.getDisplayName() }}
Check the presenter for a getter method where the method is the camel case of is_{attribute_name}.
$presenter->enabled; // Returns: $presenter->isEnabled();
{{ presenter.enabled }} // Returns: {{ presenter.isEnabled() }}
Check the decorated object for a getter method where the method is the camel case of get_{attribute_name}.
$presenter->display_name; // Returns: $presenter->getObject()->getDisplayName();
{{ presenter.display_name }} // Returns: {{ presenter.getObject().getDisplayName() }}
Check the decorated object for a boolean getter method where the method is the camel case of is_{attribute_name}.
$presenter->enabled; // Returns: $presenter->getObject()->isEnabled();
{{ presenter.enabled }} // Returns: {{ presenter.getObject().isEnabled() }}
Check the decorated object for a method where the method is the camel case of the {attribute_name}.
$presenter->display_name; // Returns: $presenter->getObject()->displayName();
{{ presenter.display_name }} // Returns: {{ presenter.getObject().displayName() }}
Check the decorated object for a getter style hook where the hook is get_{attribute_name}.
$presenter->display_name; // Returns: $presenter->getObject()->call('get_display_name');
{{ presenter.display_name }} // Returns: {{ presenter.getObject().call('get_display_name') }}
Check the decorated object for a standard hook where the hook is {attribute_name}.
$presenter->display_name; // Returns: $presenter->getObject()->call('display_name');
{{ presenter.display_name }} // Returns: {{ presenter.getObject().call('display_name') }}
Return the decorated object's attribute named {attribute_name}.
$presenter->display_name; // Returns: $presenter->getObject()->display_name;
{{ presenter.display_name }} // Returns: {{ presenter.getObject().display_name }}
Returns: mixed
Arguments
| Key | Required | Type | Default | Description |
|---|---|---|---|---|
|
$name |
true |
string |
none |
The attribute name being attempted. |
Example
$presenter->example; // Where example is not a property of $presenter
Twig
{{ presenter.example }}
Presenter::__call()
The __call magic method will try running the method on the decorated object. Remember the __call function is only invoked when the method does not exist on the presenter itself. So this effectively maps decorated object methods to the presenter.
Returns: mixed
Arguments
| Key | Required | Type | Default | Description |
|---|---|---|---|---|
|
$method |
true |
string |
none |
The method name. |
|
$arguments |
true |
array |
null |
An array of method arguments passed. |
Example
$presenter->exampleMethod(); // Returns: $presenter->getObject()->exampleMethod();
Twig
{{ presenter.exampleMethod() }}
Manually Decorating Objects
You can manually decorate an object with the \Anomaly\Streams\Platform\Support\Decorator class.
Decorator::decorate()
The decorate method decorates the object. It can also decorate an entire collection of presentable items.
Returns: \Anomaly\Streams\Platform\Support\Presenter or \Illuminate\Database\Eloquent\Collection
Arguments
| Key | Required | Type | Default | Description |
|---|---|---|---|---|
|
$value |
true |
mixed |
none |
The presentable object or collection of presentable items. |
Example
$decorated = $decorator->decorate($model);
Undecorating Values
The \Anomaly\Streams\Platform\Support\Decorator class can also be used for obtaining the original undecorated values.
Decorator::undecorate()
The undecorate reverses the decoration method's action. This is helpful for wrapping API methods for objects inside the view layer.
Returns: mixed
Arguments
| Key | Required | Type | Default | Description |
|---|---|---|---|---|
|
$value |
true |
mixed |
none |
The presenter or collection of presenters. |
Example
$original = $decorator->undecorate($model);
Writing Presenters
Presenters are automatically generated for you when using the make stream command:
php artisan make:stream stream_slug example.module.test
You can also create your own addon presenter in most cases by transforming the model class name into it's corresponding presenter class name:
TestModel -> TestPresenter
In all other cases all you need to do is define your own newPresenter method on the presentable class:
<?php namespace Anomaly\ExampleModule\Test;
use Robbo\Presenter\PresentableInterface;
use Anomaly\Streams\Platform\Support\Presenter;
class TestObject implements PresenterInterface
{
/**
* Return the presenter.
*
* @return string
*/
public function newPresenter()
{
return new Presenter($this);
}
}
An example presenter looks like this:
<?php namespace Anomaly\ExampleModule\Test;
use Anomaly\Streams\Platform\Support\Presenter;
class TestPresenter extends Presenter
{
/**
* Return the full name.
*
* @return string
*/
public function name()
{
return implode(' ', array_filter([$this->object->getFirstName(), $this->object->getLastName()]));
}
}
Now you can use this method in your API:
$test->name();
Or view layer:
{{ test.name() }}