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

copyandpaste's avatar

Polymorphism in User Roles

Benefits of polymorphism in user roles

instead of having multiple relationships like

$user->student_profile, $user->teacher_profile, $user->parent_profile.

you can just create a polymorphic relationship like

$user->profile and it will return either a model for student, teacher or parent...

But here's a problematic situation

The student model has a method called enroll... yet both teacherandparent` do not...

The Question

How should one handle such a situation?

Here are my thoughts

  • should I just add an if statement?
if (method_exists($user->profile, 'Enroll')){
 $user->profile->enroll();
}
  • should I use an interface (Enrollable)? but still, have an if statement
if ( $user->profile instanceof Enrollable ){
 $user->profile->enroll();
}

Note: This is my most preferred method

  • These are Role-based methods maybe I can use something like Can?
if ($user->can('enroll')) {
  $user->profile->enroll();
}

Note: The problem here is that a parent has the permission to enroll their children which is a student, therefore this is not preferable. unless you'll have two permission types be enrolled and enroll, but still not my preferred method.

  • Maybe there is another way? Hmm... 🤔 let me ask the awesome people from Laracast.
0 likes
2 replies
koramit's avatar

I would have a Person class and then extends it to Student, Teacher and Parent.

Person class has default enroll() but do nothing (or abort(403);) and then Teacher and Parent should never reach enroll UIs.

And I am not an awesome people 😅

1 like
copyandpaste's avatar

Well, I could see how you're trying to make use of Extends here... that's quite awesome for me 😊

I'm trying to see how the actual code would look like

now since we have polymorphism, we could make use of $user->profile and as I have explained above either Student, Teacher and Parent models would be returned from this relationship.

Using your method above, we can extend the three models to the person class, which would then make the enroll() method be available for all models.

this would result in a code like this

$user->profile->enroll();

Advantages

  • no more if statements since the enroll method from the parent handles this automatically for us.
  • and if you would like, to change the behavior of enroll for teacher or parents you just need to override the method on the model. (instead of abort(403))
1 like

Please or to participate in this conversation.