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 Morph Map Generator Laravel Package

spatie/laravel-morph-map-generator

Automatically generates and keeps Laravel Eloquent morph maps up to date. Models register themselves by implementing getMorphClass(), so you don’t forget to add entries. Optional auto-generation on app boot, configurable for custom model locations.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require spatie/laravel-morph-map-generator
    

    Publish the config (optional):

    php artisan vendor:publish --provider="Spatie\MorphMapGenerator\MorphMapGeneratorServiceProvider"
    
  2. First Use Case: Implement getMorphClass() in your Eloquent models:

    // app/Models/Post.php
    use Illuminate\Database\Eloquent\Model;
    
    class Post extends Model
    {
        public function getMorphClass(): string
        {
            return 'post'; // Morph map key
        }
    }
    

    The package auto-registers the model in Laravel's morph map during bootstrapping.

  3. Verify:

    dd(app('morphMap')->get('post')); // Should return Post::class
    

Implementation Patterns

Core Workflow

  1. Model Registration:

    • Every model with getMorphClass() is auto-registered when the MorphMapGeneratorServiceProvider boots.
    • No manual MorphMap::macro() calls needed.
  2. Dynamic Morph Maps:

    • Useful for polymorphic relationships, media libraries (e.g., Spatie Media Library), or event dispatching where models need consistent morph keys.
    • Example:
      // Polymorphic relationship
      class Comment extends Model
      {
          public function commentable()
          {
              return $this->morphTo();
          }
      }
      
  3. Integration with Existing Code:

    • Replace hardcoded morph keys (e.g., 'posts') with dynamic calls:
      // Before (manual)
      MorphMap::macro('post', Post::class);
      
      // After (auto-generated)
      $morphKey = 'post'; // From Post::getMorphClass()
      
  4. Testing:

    • Mock the morph map in tests:
      $this->app->singleton('morphMap', fn() => new MorphMap([
          'test' => TestModel::class,
      ]));
      

Advanced Patterns

  • Conditional Morph Keys: Use getMorphClass() logic to return dynamic keys (e.g., based on model state):

    public function getMorphClass(): string
    {
        return $this->isPublished() ? 'published_post' : 'draft_post';
    }
    
  • Bulk Registration: Register multiple models at once via a trait:

    trait RegistersMorphMap
    {
        protected static function bootRegistersMorphMap()
        {
            if (static::getMorphClass()) {
                app('morphMap')->macro(static::getMorphClass(), static::class);
            }
        }
    }
    
  • Overriding Default Behavior: Extend the service provider to customize registration:

    // app/Providers/MorphMapServiceProvider.php
    use Spatie\MorphMapGenerator\MorphMapGeneratorServiceProvider as BaseProvider;
    
    class MorphMapServiceProvider extends BaseProvider
    {
        public function register()
        {
            parent::register();
            // Custom logic here
        }
    }
    

Gotchas and Tips

Pitfalls

  1. Missing getMorphClass():

    • Models without this method won’t auto-register. Debug with:
      dd(app('morphMap')->getAllMappings());
      
  2. Case Sensitivity:

    • Morph keys are case-sensitive. Ensure consistency:
      // ❌ Fails if morph key is 'Post' but method returns 'post'
      public function getMorphClass(): string { return 'Post'; }
      
  3. Caching Issues:

    • Clear config cache if morph maps appear stale:
      php artisan config:clear
      
  4. Service Provider Boot Order:

    • Ensure MorphMapGeneratorServiceProvider loads before other providers that rely on morph maps (e.g., Spatie Media Library).

Debugging

  • Inspect Morph Map:
    dd(app('morphMap')->getAllMappings());
    
  • Check Registration: Add a booted event listener to verify:
    Model::booted(function () {
        if (method_exists($this, 'getMorphClass')) {
            dd('Morph key registered:', $this->getMorphClass());
        }
    });
    

Tips

  1. Consistent Naming: Use kebab-case for morph keys (e.g., blog-post) to avoid conflicts with reserved words.

  2. Testing: Reset the morph map in tests:

    $this->app->singleton('morphMap', fn() => new MorphMap());
    
  3. Performance: The package adds minimal overhead (~1ms per request). Benchmark if using in high-frequency loops.

  4. Extending: Add custom logic via the registering event:

    MorphMapGenerator::registering(function (Model $model) {
        if ($model instanceof AdminPost) {
            $model->setMorphClass('admin-post');
        }
    });
    
  5. Legacy Code: For models without getMorphClass(), manually register them in AppServiceProvider:

    MorphMap::macro('legacy_model', LegacyModel::class);
    
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.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport