davidhemphill / presenter by davidhemphill

Easy Model Presenters in Laravel
434,639
249
6
Package Data
Maintainer Username: davidhemphill
Maintainer Contact: davidlee.hemphill@gmail.com (David Hemphill)
Package Create Date: 2016-09-04
Package Last Update: 2024-03-22
Language: PHP
License: MIT
Last Refreshed: 2024-04-26 03:12:31
Package Statistics
Total Downloads: 434,639
Monthly Downloads: 6,175
Daily Downloads: 485
Total Stars: 249
Total Watchers: 6
Total Forks: 16
Total Open Issues: 0

Hemp Presenter

This package makes it fast, fun, and profitable to decorate your Eloquent models for presentation in views, responses, pdfs, csv files, or anywhere you want.

The idea for this package is explained in this post: Presenters in Laravel.

Key differences with other presenter packages

  • Supports multiple decorators/presenters
  • Decorated models can still be converted to JSON/array with toJson and toArray or by simply returning it from a controller
  • Supports mutators/magic getters like the ones used in Eloquent (e.g. getFullNameAttribute())

Installation

Install the package via composer:

composer require hemp/presenter

Presenter adds a present Collection macro whichs allows you to present a group of models. To use this, add the Service Provider to the providers array in config/app.php:

'providers' => [
    // ...

    Hemp\Presenter\PresenterServiceProvider::class,
],

Create a Presenter

<?php

namespace App\Presenters;

use Hemp\Presenter\Presenter;

class ApiPresenter extends Presenter
{
    public function createdDate() {
        return $this->model->created_at->format('n/j/Y');
    }

    public function getFullNameAttribute()
    {
        return trim($this->model->first_name . ' ' . $this->model->last_name);
    }
}

Usage

Use the present helper:

$user = User::first();
$presentedUser = present($user, ApiPresenter::class);

Or use the Presentable trait on your model and call present on it:

$presentedUser = User::first()->present(ApiPresenter::class);

Or, when using the Presentable trait, specify a default presenter using the defaultPresenter attribute on the Model and call present to use it:

$presentedUser = User::first()->present();

Use the present macro on a Collection object:

$presentedUsers = User::all()->present(ApiPresenter::class);

Once you have a presented model instance, you can use magic getters like this:

$presentedUser->full_name;

Or use regular old methods:

$presentedUser->createdAt();

Converting Presenters to JSON

Individual instances can be returned as JSON just like you can with plain Eloquent models, except the mutators you specify on your Presenter will also be serialized with the output.

public function show($id)
{
    return User::findOrFail($id)->present(ApiPresenter::class);
}

/*
// Outputs something like this
{
    "id":1,
    "full_name":"David Lee Hemphill",
    "first_name":"David",
    "last_name":"Hemphill",
    "created_at":"2016-10-14 12:00:00",
    "updated_at":"2016-12-14 12:00:00"
}
*/

A collection of presented models can be converted to JSON and array format just like normal.

public function index()
{
    return User::all()->present(ApiPresenter::class);
}

/*
// Outputs something like this
[{
    "id":1,
    "full_name":"David Lee Hemphill",
    "first_name":"David",
    "last_name":"Hemphill",
    "created_at":"2016-10-14 12:00:00",
    "updated_at":"2016-12-14 12:00:00"
},
{
    "id":1,
    "full_name":"Tess Rowlett",
    "first_name":"Tess",
    "last_name":"Rowlett",
    "created_at":"2016-10-14 12:00:00",
    "updated_at":"2016-12-14 12:00:00"
}]
*/

Hiding Attributes from array/JSON output

You can also specify $visible and $hidden properties on your Presenters. Setting $visible acts as a whitelist of attributes you want to appear in the array/JSON output. Setting $hidden acts as a blacklist of attributes you wish to be hidden from the array/JSON output. This will also remove or show any attributes from the model itself.

Using our example from earlier:

<?php

namespace App\Presenters;

use Hemp\Presenter\Presenter;

class ApiPresenter extends Presenter
{
    protected $hidden = ['first_name', 'last_name'];

    public function createdDate() {
        return $this->model->created_at->format('n/j/Y');
    }

    public function getFullNameAttribute()
    {
        return trim($this->model->first_name . ' ' . $this->model->last_name);
    }
}

This will output something like this. Notice how the first_name and last_name attributes have been removed:


/*
{
    "id":1,
    "full_name":"David Lee Hemphill",
    "created_at":"2016-10-14 12:00:00",
    "updated_at":"2016-12-14 12:00:00"
}
*/

Support

If you're using this package, I would love to know about it!

If you're having trouble getting something to work when using this package, contact me on Twitter. I'd be glad to help.

If you believe you have found an bug, improvement, or other issue, please report it using the GitHub issue tracker, or fork the repository and submit a pull request.