Search code examples
laravellaravel-nova

Laravel Nova + polymorphic Tags: when attaching "no morph map defined"


I have Tags set up in Laravel just like in the Laravel documentation example:

// App/Models/MyModel.php

public function tags()
{
   return $this->morphToMany(Tag::class, 'taggable');
}

And I added this to my Nova v3 list of fields, just like in the Nova documentation:

// App/Nova/MyModel.php

public function fields(Request $request)
{
  //...
  MorphToMany::make('Tags')
}

Existing Tags are shown just fine in Nova, but when I try to attach I get the message:

No morph map defined for model [App\Models\Tag]. There was a problem submitting the form.

When I detach a Tag the error is:

No morph map defined for model [Illuminate\Database\Eloquent\Relations\MorphPivot]

However, the Tag is detached after all and is gone after refreshing the page.

There is no problem when I manually attach / detach:

$myModel->tags()->attach($tag)

Suggestions?

update: my AppServiceProvider.php contains:

Relation::enforceMorphMap([
  'myModel' => 'App\Models\MyModel',
]);

When I disable this enforceMorphMap Nova does not have an issue. But that is unwanted, I don't want to write App\Models\MyModel to the DB, but instead only: myModel.

I tried adding to the enforceMorphMap: 'tag' => 'App\Models\Tag' (even though that is never written to the DB), but that did not have any effect.

Seems to be related to this Nova issue?
Unclear what the resolution / workaround is.


Solution

  • same issue here... After reading through the doc, I figured it out:

    Using Relation::enforceMorphMap means, it will toggle the $requireMorphMap property on:

    public static function requireMorphMap($requireMorphMap = true)
        {
            static::$requireMorphMap = $requireMorphMap;
        }
    

    then whenever you called the morph relation of Tag instance, it will call getMorphClass() where it will check whether $requireMorphMap is true via Relation::requiresMorphMap(), if it does, exception will be thrown.

     public function getMorphClass()
        {
           ...
            if (Relation::requiresMorphMap()) {
                throw new ClassMorphViolationException($this);
            }
    
            return static::class;
        }
    

    Solution:

    1/ Add a new key to your Relation::enforceMorphMap() with the model that is causing the error.

    2/ Replace the call to Relation::enforceMorphMap() with Relation::morphMap(). This will not require the morph maps anymore for your models.

    Inspired by : https://ralphjsmit.com/laravel-fix-no-morph-map-defined