# Presenter keeps display formatting out of models and views

> laracasts/Presenter is a small PHP package that adds a present() method to your entities, so the logic for how a record is displayed lives in a separate presenter object rather than in the model or in the template.

**laracasts/Presenter** — Easy view presenters in your apps.

- Repository: https://github.com/laracasts/Presenter
- Website: https://packagist.org/packages/laracasts/presenter
- Stars: 863 · Forks: 111
- Language: PHP
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/laracasts-presenter

## The problem is display logic with nowhere to live

The package starts from a familiar annoyance. You have some data, likely from an entity, and a bit of logic has to run before that data is displayed in a view. The README asks two questions and answers them both negatively. Should that logic be hard-coded into the view? No. Should it be stored in the model? No again. The reasoning behind the second answer is the one that matters for anyone who has worked in PHP: models that carry presentation concerns stop being models, and a view that computes things stops being a template. The package provides one implementation of the third option, a view presenter, which is a plain object whose only job is to format data as required. The audience is developers who find themselves writing conditional markup in a Blade template or adding a display method to an Eloquent model, and want a named, testable object in between.

## Presenters are plain objects you place wherever you like

The first step is to write your presenters, and the package is deliberately unopinionated about where they live. The README says to store them somewhere, anywhere, and describes them as simple objects that do nothing more than format data as required. A presenter extends the base Presenter class and exposes methods that return the formatted value.

```php
use Laracasts\Presenter\Presenter;

class UserPresenter extends Presenter {

    public function fullName()
    {
        return $this->first . ' ' . $this->last;
    }

    public function accountAge()
    {
        return $this->created_at->diffForHumans();
    }

}
```

The properties the presenter reads, first, last and created_at, come from the entity it wraps, so a presenter method reads like a template expression but lives in a class you can unit test. The flexibility is a double-edged sword. Because the package does not define a directory, namespace or base directory for presenters, the convention falls to your project, and a team of several developers will otherwise invent several conventions.

## The trait wires the presenter to the entity by class name

The second step is to attach the presenter to the entity. The package provides a PresentableTrait, and the README says it will automatically instantiate your presenter class. The entity declares which class to use through a protected property.

```php
<?php

use Laracasts\Presenter\PresentableTrait;

class User extends \Eloquent {

    use PresentableTrait;

    protected $presenter = 'UserPresenter';

}
```

Two things follow from that design. The presenter is resolved by class name string, which means the autoloader has to be able to find it, and there is no container involved, so a presenter with constructor dependencies is not something this wiring supports out of the box. The example entity is a Laravel User model extending Eloquent, which tells you the intended context even though the trait itself is not tied to Laravel. The package is a plain PHP library, and the Eloquent model in the README is an illustration of a common case rather than a hard requirement.

## The view calls present() and the call site documents itself

In the template, the entity exposes a present() method that returns the presenter, new or cached.

```php
    <h1>Hello, {{ $user->present()->fullName }}</h1>
```

The README draws attention to the benefit of that call beyond the formatting itself. Because the template names the presenter method explicitly, it becomes obvious where to go if the way a full name is displayed has to change, which is exactly the question a reader of a template cannot otherwise answer. The README also notes that the call returns a new or cached presenter object, so the same presenter instance is reused rather than rebuilt on every access. That caching detail matters for presenters that do real work, since a presenter method that hits the database would otherwise be a performance problem introduced by the pattern meant to improve testability.

## Installation goes through Composer, and the documented version is stale

The package is pulled in through Composer, and the README shows the requirement block.

```js
{
    "require": {
        "laracasts/presenter": "0.1.*"
    }
}
```

There is a mismatch here that will bite someone following the instructions literally. The constraint shown in the README pins the 0.1 line, while the recent release tags are 0.2.9 from 2026-08-25, 0.2.8 from 2025-04-07 and 0.2.7 from 2024-05-10. The 0.1 constraint excludes every current release, so anyone copying that block verbatim installs an old line of the package rather than the one the project maintains today. The package itself is listed on Packagist as laracasts/presenter, and the correct constraint for the current line is a 0.2 constraint, not the one in the readme. The repository root shows a small, tidy project: src/ for the library, spec/ for the tests, a phpspec.yml configuration, a composer.json, a LICENSE file and a .travis.yml file for continuous integration.

## What the package deliberately does not give you

There is no documentation in the repository beyond the readme, and the readme is short. There is no guide to how to organise presenter classes, no explanation of how the caching of the presenter instance works, no list of the public methods the base Presenter class exposes beyond the magic property access, and no mention of a way to inject a presenter. There is also no documented way to resolve presenters from a container, no collection or array presenter, and no support for pagination or resource transformation, which are the concerns that come up immediately in an API codebase. The licence is MIT, so the code can be used freely and the small surface means forking it is a realistic option if you need behaviour the package does not provide. The trade-off of a small package is that the things it does not do are your responsibility, and the reference implementation is four methods long.

## Where a presenter layer is the wrong shape of fix

A presenter solves one specific problem and creates a second. If your views are thin because you use a template system with proper view models or a front end framework that fetches JSON, a presenter layer is an extra hop with no payoff. If your team has already agreed on a convention where a Resource or a DTO handles presentation, adding presenters alongside it means two conventions and confusion about which one owns formatting. The other failure mode is duplication across presenters. A full name is not the only place a name appears, and a date format is not the only place a date appears, so a presenter class can end up being a second place where formatting rules live, only with a class name to point at. If your application has more than one way to render the same entity, the same argument applies: the presenter is a good single answer, and a bad answer to a question of multiplicity. The package solves the hard-coded view problem and the fat model problem, and it does not solve the problem of one entity rendered many ways.

## Conclusion

Presenter suits a PHP team whose views are accumulating display logic, especially one that wants a clear seam between an entity and the way it is rendered, and the present() call in the template makes that seam visible to anyone reading the markup. It is the wrong tool for a codebase with no presentation layer worth separating, and it is the wrong tool if you need presenters to be resolved from a container, since the trait instantiates the presenter class by name rather than through a binding. Before adopting it, check the version constraint in your composer.json, because the README still shows 0.1.* while the current release is 0.2.9, decide where presenter classes live given the package leaves the location to you, and confirm the trait's presenter property resolves to a class your autoloader can find. The last push was on 2026-08-25 and the current release is v0.2.9 from the same day.

## FAQ

### How do I install the laracasts/presenter package?

It is a Composer package, published on Packagist as laracasts/presenter. Note that the README still shows a 0.1.* constraint while the current release is 0.2.9, so the version constraint in your composer.json needs to match the line you actually want.

### How do I attach a presenter to a model in laracasts/presenter?

Use the Laracasts\Presenter\PresentableTrait in the entity and set a protected $presenter property to the presenter class name. The trait then instantiates that class and exposes it through the present() method.

### Where should presenter classes live?

The README says to store them somewhere, anywhere, and describes them as simple objects that format data. The package imposes no directory or namespace, so the convention is up to your project.

### Does the present() method create a new presenter every time?

The README describes the call as returning your new or cached presenter object, so the presenter instance is reused rather than rebuilt on each access.

## Sources

- [laracasts/Presenter on GitHub](https://github.com/laracasts/Presenter)
- [License: MIT](https://github.com/laracasts/Presenter/blob/master/LICENSE)
- [Project website](https://packagist.org/packages/laracasts/presenter)
- [README](https://github.com/laracasts/Presenter/blob/master/README.md)
- [Releases](https://github.com/laracasts/Presenter/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/laracasts-presenter
