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

MThomas's avatar

Attribute casting, Date Mutators on pivot table of related models

Is it possible to use Attribute Casting and/or Date Mutators on the pivot table of two related Many To Many models?

In one case I have an User and Activity model. The related pivot table has an 'payload' column, this is an column where I store serialized json. I like to cast this attribute to an array.

In an other case I have an User and Action model. The related pivot table has an 'completed_at' column. in this case I wan't to add the 'completed_at' column to the attributes that will be transformed to Carbon objects.

For the first situation I tried, but none worked:

protected $casts = [
    'activities.pivot.payload' => 'array',
];

protected $casts = [
    'activities.payload' => 'array',
];

To leverage Carbon on the 'completed_at' attribute I tried (but this also did not work):

protected $dates = ['actions.completed_at'];

protected $dates = ['actions.pivot.completed_at'];

Does anyone have any thoughts on this matter?

0 likes
11 replies
pmall's avatar

Is it for displaying your collection as array/json ?

MThomas's avatar

@JarekTkaczyk That might not be an bad work arround. I could crate a 'pivots()' relationship between the Model and Pivot table and create a PivotModel for the pivottable.

@pmall no the action model is used to track the actions of the user on the website. Think of it as a user activity log, User A added items 1, 2 and 3, commented on item 5 etc. But to prevent the table from having a column for 'product_id', 'comment_id' etc I came up with the idea to store this kind of information as a json string in a column titled 'payload'. And I want to use the attribute casting to magically transform the json string to a array :)

I opted for the approach above in order to be able to store multiple payload items for one Activity. But if I won't get this to work I will store the payload in a separate table and store the field name and model there as well.

pmall's avatar

But to prevent the table from having a column for 'product_id', 'comment_id' etc I came up with the idea to store this kind of information as a json string in a column titled 'payload'.

What about polymorphic relationship ?

In fact I don't understand what represents the activities table and why it needs a M-M relationship with user. Why not just User hasMany Activity ?

JarekTkaczyk's avatar

@pmall Yeah, that's what I'm thinking as well. @MThomas Is there arbitrary number of actions that you may want to track, or is it fixed?

MThomas's avatar

@pmall and @JarekTkaczyk

The Activity model/table holds a set of activities, lets say for example: user.created, user.update, podcast.purchased, podcast.refunded, store.opened etc. These are a pre-defined set of activities, that can be performed by the user, and in the pivot table a kind of log of these actions is stored.

And it is always a user who will perform this action, he/she will update his or her profile, will purchase a podcast etc. But in the example of a podcast refund. The podcast is refunded by the store owner to the user that purchased the podcast before and is related to a specific store (a user can have more than one store). This means that the entry for the action 'podcast.refunded' would be:

| activity_id | user_id | payload                                               |
|-------------|---------|-------------------------------------------------------|
|           3 |       1 | {"customer_id": 99, "podcast_id": 24, "store_id": 36} |

with the Store owners user_id as 1, the customers user_id as 99. And the activity_id (podcast.refunded) as 3.

Since the payload can hold multiple 'external' id's I came up with this approach, but if there is a better one, I'm open to all suggestions :)

pmall's avatar

Why not just have an activities tables with a hasMany relationship with the users ?

| type             | user_id | payload                                               |
|------------------|---------|-------------------------------------------------------|
| podcast.refunded |       1 | {"customer_id": 99, "podcast_id": 24, "store_id": 36} |
MThomas's avatar

@pmall and @JarekTkaczyk I've been thinking about that approach at first, but that does not provide me with an location to define the available activities (or I would have to do that in the class itself).

pmall's avatar

@MThomas keep the original schema but create an entity for your pivot table (and rename it with a suitable name by the way. I'll call it actions here. ActivityLog, whatever). The problem here is you want to use many to many relationship whereas you are interested in the has many relationship between the user and its actions. In fact you dont need a many to many relationship but two has many (users => actions and activities => actions). You will end with something like this :

foreach($user->actions as $action)
{
  $action_activity = $action->activity;
  $action_payload = $action->payload;
}

And you can use typecasting in your action model.

lprice's avatar

@MThomas hey there, did you find a solution to this as I'm wondering also how to solve a similar problem?

1 like

Please or to participate in this conversation.