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.

**Note:** All **presentable** objects including entry models and collections are automatically decorated with a presenter in the view layer.

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() }}
**Pro Tip:** This method is very useful when working with API objects in the view layer where the **instance** is generally required and not the **presenter**.
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() }}
**Caution:** Presenters globally block calls to **delete**, save, and update.
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);
**Note:** Non-presentable values will be returned as is.
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);
**Note:** Non-presentable values will be returned as is.

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