Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

cully's avatar
Level 3

Polymorphic relationship is not inserting type in database

In my app, a Comment can be made by either a User or a Contact. In order to set this up, I created a polymorphic relationship between the three models. However, when I try and save the user to the comment, it never inserts the user_type in the database.

Here is what I have for the insert

    $contact = User::where('email',$email->sender)->first();
    $comment->user->attach($contact);

App\Comment


class Comment extends Model
{
    protected $fillable = ['ticket_id','comment','user_id','comment_type_id','user_type'];
    public function user()
    {
        return $this->morphTo();

    }
}

App\User

class User extends Model 
{

    public function comments()
    {
        return $this->morphMany('App\Comment','user');
    }
}

App\Contact

class Contact extends Model 
{

    public function comments()
    {
        return $this->morphMany('App\Comment','user');
    }
}

My comments table looks like this

comments
    - ticket_id
    - comment
    - user_id
    - user_type
    - comment_type_id

Any idea what is going on?

0 likes
4 replies
ctroms's avatar

You have deviated slightly from the convention that allows the ORM to interact with this relationship. In a polymorphic relationship, Laravel will look for 2 columns in a specific format. Your table name in the singular with 'able' appended then suffixed with _id and _type respectively. In your case you will want to modify your comments table with the following

comments
    - id
    - commentable_id
    - commentable_type
    - ticket_id
    - comment

Then in your Comment Model you user method should be replaced with

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

Finally in your User and Contact Models change your comments method slightly

public function comments()
{
    return $this->morphMany('App\Comment', 'commentable');
}
cully's avatar
Level 3

So, If I wanted to get the User's name that commented, I would say $comment->commentable->name? Right now if I say, $comment->user->name it works and it reads better. Are you sure it looks for the "able" ending? I thought the second argument of the morphMany function designated what the function would be called.

ctroms's avatar
ctroms
Best Answer
Level 15

@cullymason The second argument to the morphMany method is the name of the prefix for the column in your comments table rather than the function on the model. That is what Laravel uses to determine that it needs the xxxx_type and xxxx_id columns. If, on your user model you defined:

public function comments()
{
   return $this->morphMany('App\Comment','user');
}

then you would need to have a user_id and user_type column on your comments table. Because Laravel is so awesome, morphMany even allows you to further customize the column name by passing additional arguments for type, id and localkey as defined in the API. If you don't provide them, the defaults are used.

I completely understand you desire for better readability. You can always add another method to your Comment model that simply wraps commentable().

public function user()
{
    return $this->commentable();
}
1 like

Please or to participate in this conversation.