mccool/laravel-auto-presenter
Installation:
composer require mccool/laravel-auto-presenter
Publish the config (optional):
php artisan vendor:publish --provider="McCool\LaravelAutoPresenter\AutoPresenterServiceProvider"
Define a Presenter:
Create a presenter class (e.g., app/Presenters/UserPresenter.php):
namespace App\Presenters;
use McCool\LaravelAutoPresenter\Presenter;
class UserPresenter extends Presenter
{
public function fullName()
{
return $this->model->name;
}
}
Bind the Presenter:
Register the presenter in config/autopresenter.php:
'bindings' => [
\App\Models\User::class => \App\Presenters\UserPresenter::class,
],
First Use Case: Pass a model to a view—it will automatically be decorated:
return view('user.profile', ['user' => $user]);
In the view, access presenter methods:
{{ $user->fullName() }}
View Binding:
User::with('posts')->get() will decorate both User and Post models).Presenter Logic:
$this->model to access the underlying model.Presenter base class methods like:
linkTo() for URL generation.trans() for localization.html() for HTML escaping.getAttribute() or setAttribute() for dynamic properties.Conditional Decoration:
false in a presenter’s __invoke method:
public function __invoke()
{
if ($this->model->isHidden()) {
return false;
}
return $this;
}
API Responses:
AutoPresenter::present():
return response()->json(AutoPresenter::present($user));
Testing:
$this->app->bind(\App\Presenters\UserPresenter::class, function () {
return new \App\Presenters\MockUserPresenter();
});
Service Providers:
Dynamically bind presenters in the boot() method:
$this->app->bind(\App\Models\Product::class, function () {
return \App\Presenters\ProductPresenter::class;
});
Middleware: Decorate models before they reach the view:
public function handle($request, Closure $next)
{
$response = $next($request);
if ($response->hasView()) {
$view = $response->getContent();
// Manually trigger decoration if needed
}
return $response;
}
Blade Directives: Create custom directives to simplify presenter usage:
Blade::directive('present', function ($expression) {
return "<?php echo AutoPresenter::present({$expression}); ?>";
});
Usage:
@present($user)
Caching: Cache presenter instances for performance:
public function __construct()
{
$this->model = Cache::remember(
"presenter_{$this->model->id}",
now()->addHours(1),
fn() => $this->model
);
}
Circular References:
User->Posts->Comments->User) can cause infinite loops.AutoPresenter::present($model, ['depth' => 2]) to limit recursion depth.Presenter Overrides:
false in __invoke, the model will not be decorated, which can break expectations.dd(AutoPresenter::present($model) instanceof \App\Presenters\UserPresenter);
Configuration Conflicts:
bindings array in config/autopresenter.php takes precedence over service provider bindings.AutoPresenter::bind() in service providers to dynamically override config values.Performance Overhead:
AutoPresenter::disable();
// Your code here
AutoPresenter::enable();
Blade Caching:
php artisan view:clear
Check Active Presenters:
dd(AutoPresenter::getBindings());
Inspect Decorated Models:
dd(AutoPresenter::present($model));
Disable Auto-Presentation:
Temporarily disable in AppServiceProvider:
public function boot()
{
AutoPresenter::disable();
// Your logic here
AutoPresenter::enable();
}
Presenter Not Triggering:
\App\Models\User, not User).composer dump-autoload).Custom Decorators:
Extend the Presenter class to add global methods:
namespace App\Presenters;
use McCool\LaravelAutoPresenter\Presenter;
class BasePresenter extends Presenter
{
public function isActive()
{
return $this->model->active;
}
}
Then extend other presenters from BasePresenter.
Event-Based Decoration:
Listen for AutoPresenter.Decorating events to modify decoration logic:
event(new AutoPresenter\Events\Decorating($model, $presenter));
Conditional Bindings:
Use closures in config/autopresenter.php for dynamic bindings:
'bindings' => [
\App\Models\User::class => function ($model) {
return $model->isAdmin() ? AdminUserPresenter::class : UserPresenter::class;
},
],
Presenter Factories: Create a factory class to centralize presenter logic:
class PresenterFactory
{
public static function create($model)
{
return match (true) {
$model instanceof User => new UserPresenter($model),
default => null,
};
}
}
Bind the factory in AutoPresenter::setFactory().
How can I help you explore Laravel packages today?