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

alxlacayo's avatar

Acitivity Feed: Polymorphic with pivot tables?

I am looking to store the activity for three actions: Follow (a user), Like & Comment (a post). Follows & Likes are represented by pivot tables. Comment is the only model.

I have three models:

  • User
  • Post
  • Comment

It seems like a Polymorphic table is what I need to store the activity, but since Likes & Comments are pivot tables how can I store this data in a polymorphic table?

The goal: I basically want a user to see: "Chris followed you", "Chris liked your photo", "Chris commented on your post". I also want to show an image of the post (if it's a like or comment action).

Do I need to convert my Likes & Follows to models and not pivot tables?

0 likes
12 replies
pmall's avatar

Why not create an activities table and fill it like a notification table.

When chris follow you insert an entry in this table with the text "Chris followed you". You can even store the other user that performed the action.

  • id
  • user_id
  • other_user_id
  • body
  • created_at

Body can even be an entry in ressource/lang so the text can be formated with a link to the other user name with its name.

alxlacayo's avatar

@pmall and how would I go about eager loading the post (if its a like or comment) or user (if its a follow) so i can either display the post image or a follow button? (basically like instagram)

pmall's avatar

Yes so it is polymorphic, a morphOne relationship

- id
- user_id
- noticeable_id
- noticeable_type
- type
- body
- created_at

Then you eager load it like anything else :

$activity_feed = Auth::user()->activities()->with('noticeable')->get();

So User hasMany Activity which morphOne Noticeable.

I added a type column so you can easily know what "type" of activity it is.

alxlacayo's avatar

@pmall thanks, but since Follows and Likes are pivot tables can't they not be stored in a Polymorphic table? Do i need to convert my Follows & Likes to models?

pmall's avatar
pmall
Best Answer
Level 56

Yes I think you should create models for them, with a primary key.

alxlacayo's avatar

@pmall Hmm ok. And to be clear on your columns 'type' would be 'follow' or 'like' or 'comment right? And what is body?

pmall's avatar

Yes because in the future type can eventually become more detailed than just the related model type. Lets say someday you want to add a new notification related to a comment, like User foo edited its comment. There would be comment and comment_update types yet it would both refer a comment.

I suggest you to create a resource/lang/en/activities.php file which contain key => text list for activities. Then the body column would refer a key from this file. This has many advantages : you can change the text of notification by changing the value associated to the key, you can have it for many languages, you can add html, etc... i think you can even remove the body column and display text based on the type.

Example :

# resource/lang/en/activities.php
return [
    'follow' => '<a href="users/:user_id">:user_name</a> folowed you'
];

Then to display the text for a follow activity :

@if ($activity->type == 'follow')
trans('activities.follow', [
    'user_id' => $activity->noticeable->follower->id, 
    'user_name' => 'user_id' => $activity->follower->user->name,
    // noticeable is a follow, follower is an user, names depends of your relationship
]);
@endif
alxlacayo's avatar

@pmall I ran into another issue. So Like & Comment we can say are children of a Post Model. For a follow, the parent is a User model. I'm incredibly stuck on how to eager load the parent based on the child. So if it's a Like or Comment i need to eager load the Post model. If it's a follow then I need to eager load the User model.

Notification::with( 'notifiable') correctly eager loads either the Like, Comment or Follower model. However, I cannot nest further by doing something like notifiable.post or notifiable.post.images or notifiable.user.isFollowing

Is the above table structure suited for this?

alxlacayo's avatar

@gwp yea but i can't eager load further than the polymorphic model. That tutorial doesn't nest on the polymorphic model. Something like notifiable.post.user

pmall's avatar

@alxlacayo

Notification::with( 'notifiable') correctly eager loads either the Like, Comment or Follower model. However, I cannot nest further by doing something like notifiable.post or notifiable.post.images or notifiable.user.isFollowing

Yeah it seems to be a known problem. The only workaround I can see is here : first separate the collection in as many collections as type of notifiable. Then for each collection of notifiable, use $collection->load('relationship_to_eager_load'), then merge back all collections of notifiable in one collection.

1 like

Please or to participate in this conversation.