laracasts/presenter
A lightweight presenter layer for Laravel that wraps your models and exposes clean, dedicated methods for formatting and displaying their data. Keep view logic out of models and controllers, with simple, testable presenter classes.
User, Order, Post — gets formatted independently in every Blade view, mail template, admin screen, and export. Name concatenation, currency, date locale, excerpt truncation, PII masking, default avatars. Each of those is a place a stakeholder-visible bug can appear. A presenter is one canonical definition per entity, which directly reduces the recurring "value looks wrong on screen after a release" defect class and its QA and hotfix cost.Presenter base class plus attribute proxying via a trait. In-house is genuinely feasible. The case for the package is MIT license, zero dependencies, no service provider, no config, no migrations, and an auditable surface one engineer can review in an afternoon. There is no lock-in; do not evaluate it like a vendor relationship.app/Presenters convention gives new engineers an obvious home for display logic, reducing senior review burden and review-cycle churn.Recommended decision-log entry: approve as a low-cost engineering convention, scoped to a pilot on 1–2 high-complexity models, with a one-page convention doc and a testable success criterion (measurable reduction in conditional formatting logic in those templates). Do not fund a broad refactor, and do not sequence it alongside a framework major upgrade.
Adopt when:
Look elsewhere when:
spatie/laravel-data) is the better fit; presenters solve a display problem, not a serialization problem.Guardrails to set up front, or the pattern degrades: presenters hold formatting only — never authorization or business rules; eager-load relations before presenting to avoid hidden N+1s; one presenter per model; presenters don't call other presenters; add @property PHPDoc on every presenter and gate CI with PHPStan, since magic-method proxying is opaque to static analysis; and write an explicit accessor-vs-presenter rule so two formatting mechanisms don't silently compete.
For executives (one paragraph):
We're proposing a small, no-cost engineering convention for how our Laravel app formats data for display. Today that logic is scattered across page templates and controllers, which is why display bugs recur and why minor copy or format changes require touching many files. Consolidating it into dedicated, testable classes makes those changes faster and safer, keeps our web pages, emails, and any future mobile or partner interface consistent, and lowers onboarding cost for new engineers. The package is MIT-licensed, has no dependencies, adds no infrastructure, and integrates in under a day. This is a tactical quality improvement inside existing feature work — not a new platform, not a line on the roadmap — and we're recommending a scoped pilot on two models before any wider rollout.
For engineering (the substance):
laracasts/presentergives us aPresenterbase class so display logic moves out of controllers and Blade intoapp/Presenters. Instead ofStr::limit($post->body, 200)and$post->created_at->format('M d, Y')repeated across templates, we write$post->present()->excerptand$post->present()->formattedDateonce and reuse them everywhere. Benefits: one place to change a format, unit-testable presentation, and a clean seam if we later move to API Resources. Costs: one new class per non-trivial model, a naming convention we must actually enforce, a documented accessor-vs-presenter rule to avoid competing mechanisms,@propertyannotations plus PHPStan to keep static analysis usable, and a real N+1 risk if presenters touch unloaded relations — so eager-loading becomes part of the convention. The package is tiny and stable but not actively developed beyond Laravel compatibility bumps; since we could rewrite it in an afternoon, that's an acceptable risk. Pin^0.2, treat it as a thin internal utility rather than a dependency we design around, and write down the copy-into-app/Supportescape hatch rather than assuming it. Proposal: pilot onUserandOrder, document the convention in the repo, and measure whether conditional logic in those templates actually drops. If it doesn't, we stop there — the sunk cost is about a day.
How can I help you explore Laravel packages today?