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

makapaka's avatar

A user has polymorphic type relationship help

I have a user that can belong to ONE of multiple different account types, I'm not sure the optimal way of setting up this relationship.

Say we have a User, that can be of account type Teacher, or Student, the base user object will contain all the shared attributes, while the teacher and student object will have the extended specific attributes for that type.

The way I see it as a kind of a mix between a pivot table and polymorphic relationship - as a User is either a teacher, or student, I can't use direct belongsTo(Student::class) or belongsTo(Teacher::class) relationship.

So if I use a pivot table called user_accounts that contains user_id, account_id, account_type, I'm unsure how to create the relationship correctly.

I expect the table to for example look like this

 user_id | account_id | account_type
      1                  3              student
      2                 4              teacher

Normally in the user model to represent a relationship you would use

public function student()
{
      return $this->belongsTo(Student::class);
}

The question is not knowing the account_type string, do we just do both $this->belongsTo(Student::class) and $this->belongsTo(Teacher::class) and let laravel deal with ignoring the invalid one, but I was wondering if it can be done dynamically, something like

public function userType()
{
    return $this->belongsToMany($accountType::class); // doesn't work
}

But I don't think this is possible ?

Also, to set up the pivot relationship, I would normally do

$this->userType()->attach($teacher/$student);

But this doesn't seem to work either.

All the above obviously has to factor in the creation of the user object, the student/teacher object and the linkage between all.

Please any pointers would help, this is the tricky part as obviously making it right up front means retrieval and querying down the track is much better/efficient.

0 likes
5 replies
tykus's avatar
tykus
Best Answer
Level 104

Does a polymorphic many-to-many make sense here (a user cannot be a student and a teacher, can they)?

Why not have a students table and a teacher table and on your users table have the xxxxaable_type and xxxxable_id (can't think of a good -able right now!).

Your relationship on User model would be

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

and on the Student and Teacher models (if they are needed):

public function user()
{
    return $this->morphOne('User', 'xxxxable');
}

Attaching records is the same as a regular belongsTo/hasOne.

Seriously, any -able I can think of, can be open to being misinterpreted

1 like
makapaka's avatar

@tykus thanks i will try this - i might have been over complicating things.

hmm typeable ?

makapaka's avatar

uh another hiccup - in User model as discussed I have

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

Is there an implicit way to say $user->typable() and get an object of that type, eg teacher, student ?

When I do that, it doesn't seem to work and I tried to add ->get() on it, which when I logged it, seemed to have the object I expected, but then when I try call a method on it, it errors with method does not exist error.

Do I have to cast it to that object model or is there a better way ? Or do I have to actually use a ::find on the teacher or student using typable_id ?

tykus's avatar

$user->typable should give you the object providing you have typable_id and typable_type columns on the users table.

Please or to participate in this conversation.