Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Presenter Laravel Package

yaro/presenter

View on GitHub
Deep Wiki
Context7

Getting Started

  • Install with composer require yaro/presenter, then confirm what you got: composer show yaro/presenter. The last tagged release is from 2021-02-22, so test it on a branch against your Laravel/PHP versions before adopting it broadly.
  • Look first at the README and vendor/yaro/presenter/src/. Identify:
    • the service provider and whether it is auto-discovered,
    • the base presenter class,
    • the trait/helper used to attach a presenter to a model,
    • composer.json constraints for illuminate/* and PHP.
  • Create one presenter for your first model, e.g. app/Presenters/UserPresenter.php. If the package supplies a base class, extend it; otherwise a small wrapper class around the model is enough to prove the pattern:
namespace App\Presenters;

use App\Models\User;

class UserPresenter
{
    public function __construct(private User $user) {}

    public function fullName(): string
    {
        return trim("{$this->user->first_name} {$this->user->last_name}");
    }

    public function createdAt(): string
    {
        return $this->user->created_at->format('M j, Y');
    }
}
  • Attach it using the package’s documented trait/property pattern if available. If the package has no trait, instantiate it directly in the controller or view:
$presenter = new UserPresenter($user);
  • First real use case: move formatting out of Blade. Replace this:
{{ $user->first_name }} {{ $user->last_name }} — {{ $user->created_at->format('M j, Y') }}

with:

{{ $user->present()->fullName }} — {{ $user->present()->createdAt }}

or, if wiring manually:

{{ (new \App\Presenters\UserPresenter($user))->fullName() }}

Implementation Patterns

  • Use one presenter per model or domain concept. Keep it focused on display concerns: names, dates, money, status labels, URLs, badges, and preformatted HTML fragments.
  • Keep presenters at the edges of the application: controllers, Blade views, API resources, mailables, and admin panels. Do not move business rules or persistence into presenters.
  • Prefer explicit presenter calls in controllers when the same model is used in multiple contexts:
public function show(User $user)
{
    return view('users.show', [
        'user' => $user,
        'presenter' => new UserPresenter($user),
    ]);
}
  • For Blade-heavy apps, the trait-based pattern is usually the least noisy:
{{ $user->present()->statusLabel() }}
  • For API resources, call the presenter inside the resource rather than exposing presenter methods on the model:
public function toArray($request): array
{
    $presenter = new UserPresenter($this->resource);

    return [
        'id' => $this->id,
        'name' => $presenter->fullName(),
        'created_at' => $presenter->createdAt(),
    ];
}
  • For collections, map consistently. If the package supports $users->map->present(), verify it; otherwise use an explicit map:
$users->map(fn (User $user) => new UserPresenter($user));
  • Inject services into presenters when formatting needs them, e.g. a money formatter, URL generator, or locale resolver. Resolve presenters through the container if they have dependencies.
  • Test presenters as plain units with model factories or unsaved models. You usually do not need a database:
$user = new User(['first_name' => 'Ada', 'last_name' => 'Lovelace']);
$this->assertSame('Ada Lovelace', (new UserPresenter($user))->fullName());
  • Use presenters in mailables and notifications too. They are a good place to centralize “friendly” output such as $order->present()->total() or $invoice->present()->dueDate().
  • If the package provides config, publish it only after reading the defaults. Avoid changing global presenter behavior unless you have a clear cross-cutting need.

Gotchas and Tips

  • Adoption risk is the main gotcha: 2 stars, 0 dependents, and a 2021 release mean you should read the source, pin the version, and be prepared to fork. If the package is only a thin trait/base class, copying the pattern into your app may be safer than depending on it.
  • Check PHP and Laravel compatibility carefully. A 2021 package may not support PHP 8.1+ or newer Laravel without deprecation warnings or method-signature issues.
  • Model serialization will not automatically include presenter methods. toArray()/JSON responses only include attributes and appended accessors. Use API resources or explicit presenter calls instead of assuming $user->present()->fullName() appears in JSON.
  • Avoid queries inside presenters. A presenter that lazy-loads relations or counts rows can create N+1 queries when used in loops. Pass loaded data in or keep presenters purely formatting-based.
  • Presenters should usually be stateless per model instance. Avoid registering a presenter as a singleton or storing request-specific state on a shared presenter.
  • If a presenter returns HTML, treat it as trusted output only after sanitization. Blade’s {{ }} will escape it; {!! !!} will not. Do not let user input flow into presenter-generated HTML unescaped.
  • Be explicit about timezone and locale. Date formatting in presenters should use the app’s configured timezone and the user’s locale where relevant; otherwise “created at” output will be inconsistent across views, mail, and APIs.
  • Watch for method collisions. If your model already has a present() method or the trait conflicts with another trait, alias the trait method or use manual presenter instantiation.
  • If something “does not work,” debug in this order: confirm the service provider is registered/auto-discovered, confirm the presenter class namespace is correct, run composer dump-autoload, clear config cache with php artisan config:clear, then dd($user->present()) or dd(new UserPresenter($user)).
  • Extension points to look for: overriding the base presenter’s model accessor, binding a presenter interface in the container, custom formatting helpers, and package config. If those do not exist, keep your presenters as small application classes rather than fighting the package.
  • Because the package is lightly adopted, add a smoke test that instantiates a presenter and asserts one formatted value. That test will catch most upgrade breakage quickly.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route