PHPackages                             brandonshar/presenters - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. brandonshar/presenters

ActiveLibrary[API Development](/categories/api)

brandonshar/presenters
======================

JSONable Presenters Objects

v0.1(8y ago)116PHPPHP &gt;=7

Since Jul 14Pushed 8y ago1 watchersCompare

[ Source](https://github.com/BrandonShar/presenters)[ Packagist](https://packagist.org/packages/brandonshar/presenters)[ RSS](/packages/brandonshar-presenters/feed)WikiDiscussions master Synced 3d ago

READMEChangelog (1)Dependencies (2)Versions (2)Used By (0)

Presenters
==========

[](#presenters)

**WARNING** While this is tested, I have not used it in a production or extensively in a development environment yet. I'm pretty sure I'm going to love using it, but until I do that I feel obligated to offer a warning about its usefulness.

### Installation

[](#installation)

Install via composer and just start using it. Couldn't be easier!

```
composer require brandonshar/presenters

```

### So what is this?

[](#so-what-is-this)

Have you ever had a model, or combination of models, that you wanted to return with different data depending on the endpoint? Maybe you have a resource controller called `VehicleOnCraigslistController` and when someone hits your `VehicleOnCraigslistController@show` method, you want to return a set of data that represents a vehicle listed on Craigslist. This set of data is likely comprised of your `Vehicle` model and your `CraigslistAd` model, but different than what you return from your `VehicleController@show` method, your `CraigslistAdController@show`, or just a combination of the two. This is where **Presenters** come in to save the day!

### How do I do those great sounding things?

[](#how-do-i-do-those-great-sounding-things)

Presenters have a number of great features. Let's see them all in action!

#### Basic Presenter Example

[](#basic-presenter-example)

```
use brandonshar\Presenter;

class VehicleOnCraigslistPresenter extends Presenter
{
  protected $vehicle;
  protected $craigslistAd;

  public function __construct(Vehicle $vehicle, CraigslistAd $craigslistAd)
  {
    $this->vehicle = $vehicle;
    $this->craigslistAd = $craigslistAd;
  }
}

$presenter = VehicleOnCraigslistPresenter::present($vehicle, $vehicle->craiglistAd);
```

There's the minimum code for a presenter! (`present` is just some nice syntactic sugar that provides a more fluent way to instantiate your presenter. If it makes you nervous, you can always new it up like usual).

Ok... I can see that you're not very impressed yet. Let's do things with it!

#### Delegation

[](#delegation)

Delegation allow you to reach through your presenter to the models (or other objects) it contains while avoiding much of the boilerplate of typical getters.

```
class VehicleOnCraigslistPresenter extends Presenter
{
  //...
  protected $delegatesTo = [
    'vehicle' => ['year', 'make'],
    'craigslistAd' => ['listedAt'],
  ];
  //...
}
```

Now we can "reach through" the presenter to access the delegates properties!

```
$presenter = VehicleOnCraigslistPresenter::present($vehicle, $vehicle->craiglistAd);

$presenter->year; //$presenter->vehicle->year;
$presenter->make; //$presenter->vehicle->make;
$presenter->listedAt; // $presenter->craigslistAd->listedAt;
```

Ok, a little cooler, right? What if we need something more complicated?

#### Getters (Accessors)

[](#getters-accessors)

The presenter has getters that work just like Laravel's Eloquent getters: just create a method called getPropertyNameAttribute (if your property is called "propertyName") that optionally accepts a single argument (the currently set value of the named property) :

```
class VehicleOnCraigslistPresenter extends Presenter
{
  //...
  public function getVehicleTitleAttribute()
  {
    return "{$this->vehicle->year} {$this->vehicle->make} {$this->vehicle->model}";
  }

  public function getCachedAtAttribute($currentValue)
  {
    return DateTime::createFromFormat('Y-m-d', $currentValue)->format('l, M jS');
  }
  //...
}
```

We can now access this like any other property:

```
$presenter->vehicleTitle;
//or if you prefer
$presenter->vehicle_title;
```

Both camelCase and snake\_case work the same. If you put information into your presenter manually, it will automatically be passed as an argument to your getter.

```
$presenter->cachedAt = '2017-09-21';
echo $presenter->cachedAt; //Thursday, Sept 21st
```

**Note:** Wish you had a better way to put data on your presenter? Just hang tight for the tap method below!

##### getAttribute

[](#getattribute)

If you need to access an attribute that isn't the attribute named in your getter, you should use the `getAttribute` method:

```
return $this->getAttribute('cachedAt');
//or (they both work the same)
return $this->getAttribute('cached_at');
```

You could go directly to the `attributes` array property, but this requires you to make sure you match case with the json casting below (defaulting to snake\_case). Because of this, the preferred way is to use the get (and corresponding set) attribute methods.

#### Setters (Mutators)

[](#setters-mutators)

Technically, the presenters do have setters, but I haven't thought of a use case for them. They exist in order to aid the getters, but could be used standalone. I haven't thought of a real use case for them, but here's a quick example in case you do:

```
public function setSomeExampleAttribute($value)
{
  $this->setAttribute('someExample', strtoupper($value));
}
```

Now you can:

```
$presenter->someExample = 'my message';
echo $presenter->someExample; //MY MESSAGE
```

##### setAttribute

[](#setattribute)

Just like getting above, the preferred way to set internal attributes is as follows:

```
$this->setAttribute('someExample', $value);
// or
$this->setAttribute('some_example', $value);
```

#### Tap

[](#tap)

I'm a sucker for fluid syntax and avoiding temporary variables, so if you want to add some instance variables to your presenter when it's instantiated, you can do so with the tap method:

```
$presenter = VehicleOnCraigslistPresenter::present($vehicle, $vehicle->craiglistAd)->tap(function ($presenter) {
  $presenter->cachedAt = date('Y-m-d');
});

echo $presenter->cachedAt; //Thursday, Sept 21st (don't forget our getter from above)
```

#### Json

[](#json)

I try to exclusively develop API endpoints to be consumed by my front-end, so my use cases for this are always json. If you're like me, then you'll be happy to know that you have three great ways to get json out of your presenter: You can use the toJson method:

```
echo $presenter->toJson();
```

You can simply use the php function json\_encode (presenters implement `JsonSerializable`)

```
echo json_encode($presenter);
```

OR if you use Laravel (and if you don't, you should strongly reconsider), you can just directly return presenters from any controller route and they'll be converted to json automatically! This is where the code really starts to get sexy:

```
return VehicleOnCraigslistPresenter::present($vehicle, $vehicle->craiglistAd)->tap(function ($p) {
  $p->cachedAt = date('Y-m-d');
});
```

#### Wait, what is converted to JSON?

[](#wait-what-is-converted-to-json)

Presenters automatically turn all of their delegates, any getters, and any variables that were manually set (through tap or otherwise) as JSON. Our json from the presenter we've been building will look something like this:

```
{"year": 2015, "make": "Chevy", "listed_at": "2017-08-01", "vehicle_title": "2015 Chevy Volt", "cached_at": "Thursday, Sept 21st", "some_example": "MY MESSAGE"}
```

#### But hang on, I prefer my JSON to be camelCase? Is there any hope for me?

[](#but-hang-on-i-prefer-my-json-to-be-camelcase-is-there-any-hope-for-me)

Oh come on, how on earth would we manage to make something like.. OH WAIT ONE SECOND

```
class VehicleOnCraigslistPresenter extends Presenter
{
  //...
  protected $jsonEncodeCase = 'camel';
  //...
}
```

Happy? Valid options are `camel`, `snake`, or (if you're an irredeemable monster), `studly`

That's all for now! I hope to update as I begin using this in my projects more and would be irrationally thrilled to receive a pull request if you think you can improve it.
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

[](#thats-all-for-now-i-hope-to-update-as-i-begin-using-this-in-my-projects-more-and-would-be-irrationally-thrilled-to-receive-a-pull-request-if-you-think-you-can-improve-it)

###  Health Score

24

—

LowBetter than 32% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity7

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity53

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

3227d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/34863929d4af0abbfb1aaeff071a6548385c3bcd92b940fbcc5897a4c4b15114?d=identicon)[BrandonShar](/maintainers/BrandonShar)

---

Top Contributors

[![BrandonShar](https://avatars.githubusercontent.com/u/6599653?v=4)](https://github.com/BrandonShar "BrandonShar (11 commits)")

---

Tags

apijsonphppresenterresponse

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/brandonshar-presenters/health.svg)

```
[![Health](https://phpackages.com/badges/brandonshar-presenters/health.svg)](https://phpackages.com/packages/brandonshar-presenters)
```

###  Alternatives

[stripe/stripe-php

Stripe PHP Library

4.0k143.3M480](/packages/stripe-stripe-php)[twilio/sdk

A PHP wrapper for Twilio's API

1.6k92.9M272](/packages/twilio-sdk)[knplabs/github-api

GitHub API v3 client

2.2k15.8M187](/packages/knplabs-github-api)[facebook/php-business-sdk

PHP SDK for Facebook Business

90121.9M34](/packages/facebook-php-business-sdk)[meilisearch/meilisearch-php

PHP wrapper for the Meilisearch API

73813.7M114](/packages/meilisearch-meilisearch-php)[google/gax

Google API Core for PHP

263103.1M454](/packages/google-gax)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
