Search code examples
laravelpolymorphic-associations

How to manually set the value that is stored in model type column in polymorphic relations?


Consider the following tables:

staff
    id - integer
    name - string

products
    id - integer
    price - integer

photos
    id - integer
    path - string
    imageable_id - integer
    imageable_type - string

Laravel by default stores the name of model class in imageable_type column .e.g App\Product and App\Staff. How to manually set the type values? e.g. product and staff.


Solution

  • On Laravel >= 5.1.14, you should set the static Relation::morphMap property to define all morph classes for your application.

    In the boot() method of your AppServiceProvider, add the following:

    \Illuminate\Database\Eloquent\Relations\Relation::morphMap([
        'product' => 'App\Product ',
        'staff' => 'App\Staff ',
    ]);
    

    If using Laravel < 5.1.14, the morphMap functionality doesn't exist. However, you can set the morphClass attribute on the model. This will let you set the value that is used inside the *_type field.

    class Product extends Model
    {
        protected $morphClass = 'product';
    }
    
    class Staff extends Model
    {
        protected $morphClass = 'staff';
    }
    

    The issue with this approach, however, is that you won't be able to get the parent record from the morphed record. So, if you have a Product or Staff model, you'll be able to get the Photo just fine. But, if you have a Photo model, you won't be able to get the related Product or Staff record that easily. The issue and the solution to the issue are described this question and answer.

    The morphMap functionality provided in Laravel >= 5.1.14 does not have this issue.