-
Notifications
You must be signed in to change notification settings - Fork 35
Description
- Laravel Version: 5.60.0
- Nova Version: 3.29.0
- PHP Version: 7.4
- Database Driver & Version: MySql 8
TL;DR
Getting this exception on a belongsToMany relation via pivot after switching to Relation::enforceMorphMap as there isn't a mapping for Illuminate\Database\Eloquent\Relations\Pivot?!
Illuminate\Database\ClassMorphViolationException: No morph map defined for model
[Illuminate\Database\Eloquent\Relations\Pivot].
in /vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasRelationships.php:736
Stack trace:
#0 /vendor/laravel/nova/src/Actions/ActionEvent.php(132): Illuminate\Database\Eloquent\Model->getMorphClass()
#1 /vendor/laravel/nova/src/Http/Controllers/ResourceAttachController.php(41): Laravel\Nova\Actions\ActionEvent::forAttachedResource(Object(Laravel\Nova\Http\Requests\NovaRequest), Object(App\Models\Admin), Object(Illuminate\Database\Eloquent\Relations\Pivot))
#2 /vendor/laravel/framework/src/Illuminate/Database/Concerns/ManagesTransactions.php(29): Laravel\Nova\Http\Controllers\ResourceAttachController->Laravel\Nova\Http\Controllers\{closure}(Object(Illuminate\Database\MySqlConnection))
#3 /vendor/laravel/framework/src/Illuminate/Database/DatabaseManager.php(388): Illuminate\Database\Connection->transaction(Object(Closure))
#4 /vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php(261): Illuminate\Database\DatabaseManager->__call('transaction', Array)
#5 /vendor/laravel/nova/src/Http/Controllers/ResourceAttachController.php(46): Illuminate\Support\Facades\Facade::__callStatic('transaction', Array)
Description:
Laravel PR of change merged: laravel/framework#38656
Laravel version released in 8.59.0
Docs were changed to suggest only using this method:
https://laravel.com/docs/8.x/eloquent-relationships#custom-polymorphic-types
If you use the old Relation::morphMap this works fine still, however, to be strict about morph types it seems that it is now recommended to switch to Relation::enforceMorphMap
Detailed steps to reproduce the issue on a fresh Nova installation:
See the example structure and code below taken from laravel docs:
https://laravel.com/docs/8.x/eloquent-relationships#many-to-many
If you try and attach a role to the user in nova with this setup you will get the above error.
Structure
users
id - integer
name - string
roles
id - integer
name - string
role_user
user_id - integer
role_id - integer
Model
class User extends Model
{
public function roles()
{
return $this->belongsToMany(Role::class);
}
}AppServiceProvider@register - Relation::enforceMorphMap:
Relation::enforceMorphMap([]);App/Nova/UserResource@fields
BelongsToMany::make('Roles', 'roles', RoleResource::class)Workaround
Add pivot classes to morph map:
Relation::enforceMorphMap([
MorphPivot::class => MorphPivot::class,
Pivot::class => Pivot::class,
]);Note: I believe that a polymorphic pivot will have the same error with resolving the MorphPivot class and will need to have the same fix as this error.
Conclusion
It seems that the ActionEvent::forAttachedResource is getting Illuminate\Database\Eloquent\Relations\Pivot as the $pivot rather than a model and calls getMorphClass() on it which errors as it doesn't exist in the enforced morph map.