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

sebastiaanluca/laravel-auto-morph-map

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require sebastiaanluca/laravel-auto-morph-map
    

    Publish the config file (if needed):

    php artisan vendor:publish --provider="SebastiaanLuca\AutoMorphMap\AutoMorphMapServiceProvider"
    
  2. Basic Configuration: Edit config/automorphmap.php to define your morph map aliases. Example:

    'morph_map' => [
        'App\Models\Post' => 'post',
        'App\Models\Video' => 'video',
        'App\Models\User'  => 'user',
    ],
    
  3. First Use Case: Define a polymorphic relationship in your Comment model:

    public function commentable()
    {
        return $this->morphTo();
    }
    

    Now, when querying Comment::find(1)->commentable, the commentable_type column will store 'post' or 'video' instead of the full class name.


Implementation Patterns

Common Workflows

  1. Consistent Database Schema: Use the package to enforce uniform *_type column values across environments (e.g., post instead of App\Models\Post or App\Entities\Post). Example:

    // config/automorphmap.php
    'morph_map' => [
        'App\Models\Post' => 'post',
        'App\Entities\Post' => 'post', // Maps to the same alias
    ],
    
  2. Dynamic Morph Maps: Override the morph map dynamically in a service provider or boot method:

    public function boot()
    {
        AutoMorphMap::extend(function ($morphMap) {
            $morphMap['App\Models\Article'] = 'article';
        });
    }
    
  3. Reverse Mapping (Type → Class): Retrieve the original class from an alias using AutoMorphMap::getModelForType():

    $modelClass = AutoMorphMap::getModelForType('post'); // Returns 'App\Models\Post'
    
  4. Seeding and Factories: Use the aliases in factories or seeders to ensure consistency:

    // DatabaseSeeder.php
    Comment::factory()->create([
        'commentable_type' => 'post',
        'commentable_id'   => 1,
    ]);
    
  5. API Responses: Normalize polymorphic relationships in API responses:

    return Comment::with('commentable')->get()->map(function ($comment) {
        return [
            'id' => $comment->id,
            'commentable_type' => $comment->commentable_type, // 'post' or 'video'
            'commentable_id'   => $comment->commentable_id,
        ];
    });
    
  6. Middleware for Validation: Validate polymorphic types in middleware or form requests:

    public function rules()
    {
        return [
            'commentable_type' => ['required', 'string', Rule::in(array_keys(config('automorphmap.morph_map')))],
        ];
    }
    

Gotchas and Tips

Pitfalls and Debugging

  1. Caching Issues:

    • Clear Laravel's config cache after updating config/automorphmap.php:
      php artisan config:clear
      
    • If using route/model caching, clear those as well:
      php artisan route:clear
      php artisan view:clear
      
  2. Case Sensitivity: The package is case-sensitive by default. Ensure your database values match the config keys exactly (e.g., 'post' vs 'Post').

  3. Missing Aliases: If a model isn’t mapped, Laravel falls back to the full class name. Debug by checking:

    dd(AutoMorphMap::getModelForType('unknown')); // Returns null if no match
    
  4. Dynamic Model Binding: Avoid binding polymorphic models directly by ID without the type, as it may fail silently:

    // ❌ Risky: Assumes type is correct
    $post = Post::findOrFail($request->commentable_id);
    
    // ✅ Safer: Explicitly resolve
    $commentable = AutoMorphMap::resolveModel($request->commentable_type, $request->commentable_id);
    
  5. Testing: Mock the morph map in tests to avoid hard dependencies:

    AutoMorphMap::shouldReceive('getModelForType')
        ->with('post')
        ->andReturn('App\Models\Post');
    
  6. Performance: The package adds minimal overhead. For large-scale apps, preload the morph map in a service provider:

    public function boot()
    {
        AutoMorphMap::load(config('automorphmap.morph_map'));
    }
    

Extension Points

  1. Custom Resolvers: Extend the resolver logic for complex scenarios (e.g., tenant-aware models):

    AutoMorphMap::extendResolver(function ($type) {
        return "App\\Tenants\\{$type}Model";
    });
    
  2. Environment-Specific Maps: Use environment variables or conditional logic to switch morph maps:

    'morph_map' => env('APP_ENV') === 'local'
        ? ['App\Models\Post' => 'local_post']
        : ['App\Models\Post' => 'prod_post'],
    
  3. Database Migrations: When updating the morph map, run a data migration to update existing *_type values:

    DB::table('comments')->where('commentable_type', 'App\Models\Post')->update([
        'commentable_type' => 'post',
    ]);
    
  4. Laravel Scout Integration: Use aliases in Scout full-text searchable fields:

    public function toSearchableArray()
    {
        return [
            'commentable_type' => $this->commentable_type, // 'post' or 'video'
        ];
    }
    
  5. API Contracts: Document polymorphic types in OpenAPI/Swagger specs:

    commentable_type:
      type: string
      enum: [post, video, user]
      description: Alias of the related model.
    
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.
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui