Many to many relationship using "link" method

I have some many to many relationships in my data-model that use a standard join table. When the relationships are specified in the ActiveRecords we can use the "link" method to create the row in the join table without having to specify an additional ActiveRecord. This is great and keeps things clean.

My issue is that some of my join tables I have additional attributes not just the foreign keys. For example, I have a User model and a Membership model. One User can have many different Memberships and each Membership can have many Users. each time a user purchases a membership, that membership will eventually expire. To handle this I have a "exp_date" column in the join table. Is there any way to set this extra attribute using the link method. If not I will have to create an additional ActiveRecord for many different join tables in my system. I REALLY do not want to do that.

There must be a way to do this but I have not been able to find it.


It looks to me that creating an ActiveRecord for the junction table is the most simple and clean.

Without it, how do you want to access "exp_date" of a membership of a certain user? "exp_date" is neither an attribute of User nor that of Membership.

Softark, you always come to my rescue. Thank you for that…

I suppose I could get the value by joining the two tables together using an inner join and specifying the table name (join instead of joinWith). Something along these lines…

User::find()->where(['id'=>123])->join('INNER JOIN','user_membership', 'user_membership.user_id =')

This would return my main object with an array of the additional attributes. I have done this before but can’t remember the exact syntax I used. I would be able to access the foreign attribute with something like this…

It was either like this,


or like this,


It looks too complicated for me. I’d rather go simple like the following by defining a hasMany relation from User to UserMembership and hasOne relation from UserMembership to Membership.

$user = User::find()->where(['id'=>123])->with(['userMemberships', 'userMemberships.member'])->one();

foreach($user->userMemberships as $userMembership) {

    $title = $userMembership->membership->title;

    $exp_date = $userMembership->exp_date;


It’s much easier and requires less coding. :)

I guess I don’t have any choice. I was just hoping to avoid creating more AR’s. Thanks for your time; I’ll take this approach. It will probably be betting in the long run because it is more native to the framework.