Should I create three models or a polymorphic type

Viewed 384

I have a Laravel 8 application and am wondering how to solve the problem of how to solve a typical polymorphic issue. I have an Employee model. That Employee can be an ExecutiveEmployee or EntryLevelEmployee. There will be methods an ExecutiveEmployee has that an EntryLevelEmployee doesn't have and the inverse is also true.

Using Laravel 8, is it right to create a base Employee model (without a corresponding table?) and then create two models named ExecutiveEmployee and EntryLevelEmployee that inherit from Employee? This would also imply that both employee types will have two different database tables, even though there will be a lot of overlapping data.

Does it make sense to just have one Employee model and create a migration that has the employee type listed in the model? I am assuming that it's ok if an EntryLevelEmployee has some database attributes which are relevant to it that may or may not be relevant to an ExecutiveEmployee type here, or is that an incorrect assumption?

What's the correct way to model this in Laravel 8? I prefer to keep everything in one table because of how similar the models are. I do have to keep in mind that there will be data that one has that the other doesn't. There will be different accessor methods as well.

Is it possible to have everything in one employees table while utilizing multiple models? Meaning, if I create two models named ExecutiveEmployee and EntryLevelEmployee they would both query the underlying table employees?

UPDATE 1

The more I research, the more I think polymorphism is the incorrect approach here and what I might need is Single-Table Inheritance. This package seems to bring the capability to Eloquent. Would there be a good reason to not use this?

4 Answers

I would use polymorphic relationships in this case, because you are more flexible and have less coupling.

Using the Single Table Inheritance (STI), you can add type specific columns in the employees table and make them nullable. But think about adding/removing types in the future.

executive_employees
    id - integer
    executive_specific - string

entry_level_employees
    id - integer
    entry_level_specific - string

employees
    id - integer
    name - string
    email - string
    employable_id - integer
    employable_type - string

As for the STI the same would be

employees
    id - integer
    name - string
    email - string
    type - string
    executive_specific - nullable string
    entry_level_specific - nullable string

So STI would be suitable when you don't have type specific columns. But you want to add specific behavior in your code. For example a User type (Admin, Author).

Even so, it's a matter of preferences.

It really depends on the state and behavior of your employee object.

Below are few points I will consider to make a decision

  • If your objects' states/properties are different then definitely you will create different models as your data will be stored in different tables.
  • If most states/properties are same and some are different, you can consider storing all in one table/model and for the difference in behavior create separate table like Ron Van Der Heijden has suggested and you can consider query scope with that to make transaction with database.

And another view will be

  • How many JOINs you will create if you will create different tables, will that impact the performance and other stuffs, will it make your code complex?
  • Can you make simpler relations and handle stuffs independently?
  • When you are making an API, will your code make the api overworking? or you need to create too many request for any operation?

These stuffs will decide how you will make a decision.

Update 1: Another point I would like to add about the package you are thinking to use, consider using a parent key in table and you can define relationships in a single model.I do not think you need to use a package, you can define it yourself, I guess.

I don't understand why you don't create a simple one-to-many relation. Based on the information you provided, the polymorphic relation looks unnecessary. I think the right way is to create employee_roles table and relations. Then you can give different permissions to different employee types. There are several ways to do that. You can create a middleware to create route restrictions. You can check the role before executing a function in the controller, and run only if the employee has permission. You can use if-else in blade not to render the parts that can't be used by auth user etc.

If you have different “types” of employees, and each employee type should have different logic then yeah, that sounds like a polymorphic relationship.

Related