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

mstnorris's avatar

Best way to implement two different relationships between two models

I have two models, User and Module

A User is either a student, teacher, admin staff member to name a few. They are not separate models. Maybe they should be but I have kept it this way for authentication purposes.

If a User is a student then they will belongsToMany Module (I already have this set up and working, the inverse is working too).

If however a User is a teacher then they can also belongsToMany Module however this time, rather than taking the module, they will be leading it.

  1. How can I distinguish whether the Users associated with a Module are either students or teachers.
  2. Would it be better to separate the User models into each of the respective groups, with each one extending the base User model. Is that possible?
0 likes
17 replies
martinbean's avatar

@mstnorris You can have multiple relations to the same model.

You could maybe have a Student model and a Teacher model, both of which extend your User model. Those could then have relevant methods inside:

class Student extends User
{
    public function modulesEnrolledOn()
    {
        return $this->belongsToMany('Module', 'course_student', 'student_id', 'id');
    }
}
class Teacher extends User
{
    public function modulesTeaching()
    {
        return $this->belongsToMany('Module', 'course_teacher', 'teacher_id', 'id');
    }
}

Alternatively, you could put both methods in your User class in case you have some bright, young student who is both taking courses, as well as teaching some!

mstnorris's avatar

@martinbean that's what I am battling against at the moment.

I definitely feel that I need to separate my User model into the respective "sub models" so to speak.

How would I, in this case, account for when a User is Student and a Teacher?

Also, would that affect Auth and/or any other relationships I have set up?

Could I keep common relationships on the User model, and specific ones on the sub models?

martinbean's avatar

@mstnorris As I say, you could put both the modulesEnrolledOn and modulesTeaching relations in to your core User module if that’s the case. Then it’s up to you to decide on how you classify that user.

You definitely wouldn’t want to have separate tables for students and users, and if you do have a case where a user is both a student and teacher, then you’re going to be inserted rows into two different tables for the same entity.

Djbethel's avatar

You could also use polymorphic relations for different user types.

So something like

class User{

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

}

class Student{

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

}

class Teacher{

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

}

Then when you make your user table make sure you have the columns userable_id and userable_type

Then you can do stuff like $teacher = Teacher::findOrFail(Auth::user->userable_id);

$teacher->subject

mstnorris's avatar

@Djbethel I thought about that, again, would that affect the built in Auth and other relations?

Djbethel's avatar

Nope. I use it for a project now.

I have a user table, then I have employers and employees separated.

Data like email and password and name , which are general stay in the user table Specific data to both employers and employees go in their perspective tables.

All users use the same login form. Works fine

mstnorris's avatar

@Djbethel what about common relationships? Can they still go on the User model and be accessible to all the related models?

Djbethel's avatar

Give me an example? Do you mean like School? Both teachers and students will have a relationship with a particular school?

So your asking if you can just place that relationship on the user model instead of the individual models

Djbethel's avatar

I don't see that being a problem but I've never tested a similar scenario myself

Djbethel's avatar

But I definitely know when it comes to authentication it's not a problem

mstnorris's avatar

@Djbethel in your examples above, I assume that you wrote pseudo code. Can the Student and Teacher models extend the User model? And would the morphTo relation still work, or would it effectively get stuck in a loop?

Djbethel's avatar

You wouldn't need to extend the User model, the polymorphic relationship would already do that.

My assumption (since not tested) would be that you can do something like, creating a School relationship on the User model

Then you should be able to do User::findOrFail(1)->userable()->school

userable() determines what type of user object it is based on the polymorphic relationship, and then grabs the data from that model

mstnorris's avatar

@Djbethel thank you for your help.

Another question, if I go down the polymorphic route, can a User still be a Student AND a Teacher at the same time?

Also, wouldn't I then need a students and teachers table, and so on...?

JarekTkaczyk's avatar

@mstnorris I think it's too broad to give you simple answer.

If you had 1-1 relation between User and his Role (teacher, student, whatever), then polymorphic relation would be probably the easiest way.

However, the question here is different - how do you tell what to show to the user? I suppose you have different routes/controllers/UI for different roles, don't you? Then, it doesn't matter how you link these models, because you will request data, that needs to be fetched, after you identified user's role.

For example, imagine a user who is a student and a teacher:

// student controller
$courses = $user->getModulesEnrolledOn();

// teacher controller
$courses = $user->getModulesTeaching();

Take these methods as pseudo-code just to show what I mean - you run whatever it takes to get these modules, say, in your model/repository/whatever. There will be the logic dependant on your choice (polymorphic relation, class polymorphism).

Djbethel's avatar

Yeah, Now I'm not sure if you can have two user types with polymorphic relationships. At this point maybe you'd have to have a many to many relationship with a User and a Roles table. A user can have many roles (teacher,student) and a Role can belong to many users.

Then you'd just have to do conditionals when it comes to permission stuff. So you can still just have one user table, but just check for a Users Role before doing anything

Please or to participate in this conversation.