Weave Code
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

Laravel Auto Presenter Laravel Package

mccool/laravel-auto-presenter

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require mccool/laravel-auto-presenter
    

    Publish the config (optional):

    php artisan vendor:publish --provider="McCool\LaravelAutoPresenter\AutoPresenterServiceProvider"
    
  2. 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;
        }
    }
    
  3. Bind the Presenter: Register the presenter in config/autopresenter.php:

    'bindings' => [
        \App\Models\User::class => \App\Presenters\UserPresenter::class,
    ],
    
  4. 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() }}
    

Implementation Patterns

Core Workflows

  1. View Binding:

    • Automatic Decoration: Any model passed to a view is automatically wrapped in its presenter.
    • Nested Data: Works recursively for collections, paginators, and arrays (e.g., User::with('posts')->get() will decorate both User and Post models).
  2. Presenter Logic:

    • Model Access: Use $this->model to access the underlying model.
    • Helper Methods: Leverage Presenter base class methods like:
      • linkTo() for URL generation.
      • trans() for localization.
      • html() for HTML escaping.
    • Dynamic Properties: Use getAttribute() or setAttribute() for dynamic properties.
  3. Conditional Decoration:

    • Skip decoration for specific models by returning false in a presenter’s __invoke method:
      public function __invoke()
      {
          if ($this->model->isHidden()) {
              return false;
          }
          return $this;
      }
      
  4. API Responses:

    • Decorate responses using AutoPresenter::present():
      return response()->json(AutoPresenter::present($user));
      
  5. Testing:

    • Mock presenters in tests by overriding the binding:
      $this->app->bind(\App\Presenters\UserPresenter::class, function () {
          return new \App\Presenters\MockUserPresenter();
      });
      

Integration Tips

  1. Service Providers: Dynamically bind presenters in the boot() method:

    $this->app->bind(\App\Models\Product::class, function () {
        return \App\Presenters\ProductPresenter::class;
    });
    
  2. 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;
    }
    
  3. Blade Directives: Create custom directives to simplify presenter usage:

    Blade::directive('present', function ($expression) {
        return "<?php echo AutoPresenter::present({$expression}); ?>";
    });
    

    Usage:

    @present($user)
    
  4. Caching: Cache presenter instances for performance:

    public function __construct()
    {
        $this->model = Cache::remember(
            "presenter_{$this->model->id}",
            now()->addHours(1),
            fn() => $this->model
        );
    }
    

Gotchas and Tips

Pitfalls

  1. Circular References:

    • Decorating deeply nested relationships (e.g., User->Posts->Comments->User) can cause infinite loops.
    • Fix: Use AutoPresenter::present($model, ['depth' => 2]) to limit recursion depth.
  2. Presenter Overrides:

    • If a presenter returns false in __invoke, the model will not be decorated, which can break expectations.
    • Debug: Check if a presenter is active with:
      dd(AutoPresenter::present($model) instanceof \App\Presenters\UserPresenter);
      
  3. Configuration Conflicts:

    • The bindings array in config/autopresenter.php takes precedence over service provider bindings.
    • Tip: Use AutoPresenter::bind() in service providers to dynamically override config values.
  4. Performance Overhead:

    • Auto-decoration adds minor overhead. For APIs or CLI commands, disable it temporarily:
      AutoPresenter::disable();
      // Your code here
      AutoPresenter::enable();
      
  5. Blade Caching:

    • Blade-compiled views may not reflect presenter changes until the cache is cleared:
      php artisan view:clear
      

Debugging

  1. Check Active Presenters:

    dd(AutoPresenter::getBindings());
    
  2. Inspect Decorated Models:

    dd(AutoPresenter::present($model));
    
  3. Disable Auto-Presentation: Temporarily disable in AppServiceProvider:

    public function boot()
    {
        AutoPresenter::disable();
        // Your logic here
        AutoPresenter::enable();
    }
    
  4. Presenter Not Triggering:

    • Ensure the model class matches the binding key (e.g., \App\Models\User, not User).
    • Verify the presenter is autoloaded (check composer dump-autoload).

Extension Points

  1. 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.

  2. Event-Based Decoration: Listen for AutoPresenter.Decorating events to modify decoration logic:

    event(new AutoPresenter\Events\Decorating($model, $presenter));
    
  3. 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;
        },
    ],
    
  4. 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().

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.
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium