Achieving Laravel Eloquent Model Inheritance - laravel

I currently do have a vehicles table that holds "Cars".
Now I want to allow the system to have Bikes, Cars and Trucks.
They have some fields in common (manufacturer_id, mileage, ... ) but they also have specific fields (Bike: cylinder_capacity, seats; Car: doors, ...)
I have tried using all columns in vehicles table and then use the models to handle the differences, But i had problems setting the fillable fields for the child models...
Then I read about polymorphic relations and it seems the right way to go.
So, my questions are: Which approach is the best? What is the best way to implement it?
Thanks!

Create additional tables:
vehicles_types to store types, like cars, bikes etc.
vehicles_attributes to store specific type attributes related via vehicle_type_id with fields vehicle_type_id, name, value.

I extend other models occasionally, and it works as expected. The migrations need to be set up separately, but the class logic (attributes and methods) will work in the normal OOP way. If you're familiar with this, just do what you're doing!

Related

Should I create three models or a polymorphic type

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?
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.

JPA entity relationship dependent on other field

My database has a table that represents the common fields between a bunch of other things. So lets say there's one table like Vehicle and then Vehicle has fields like VIN, color, type...
Then there are other tables like Car and Truck and when the "type" on the Vehicle is "car" we want to look at the Car table to find other properties. Maybe stuff about fuelEfficiency and numPassengers. When type is "truck" we want to know things about trucks like maybe loadCapacity or whatever.
How do you model something like this? Do you Embed the Vehicle into all of the other types? Is there a way to do like a #OneToOne between the tables conditionally on the "type" field?
You could use a MappedSuperClass or a JoinedTable strategy, if you want to follow the real ORM way of doing this. But it comes with a cost. There are other overheads, such as querying restrictions and more joins per query etc that comes with these strategies.
If you denormalize the tables, you could use a datafilter strategy (only hibernate supports I think). But now you have everything in a single class and that could be a bigger problem to deal with.
Since you are using REST, you are probably looking to cater /api/vehicles/1 (correct me pls)
For such scenarios, it is easier to perform this using a "Vehicle" table which contains the "type" in it. You can use a jackson serializer to omit all non-null components. So in the case of a car, vehicle attributes and car parameters will come in, but null values on truck, bus etc will be omitted.

When polymorphic relation shouldn't be used?

Is it okay to use a polymorphic relation when there are lets say 6 common columns and 2 columns with different names?
I need to track car maintenance and refueling.
maintenances - table
-date
-km_driven
-info (refers to maintenance info )
refuelings - table
-date
-km_driven
-amount (refers to amount in liters)
So, should i use polymorphic relationship or not? Is it ok if there are more different columns per model?
IMHO for your case I will go for single table inheritance (STI), but you need a library like this tightenco/parental or this one Nanigans/single-table-inheritance.
Laravel codebase has no support for STI without an external library. You can try to use polymorphic relation to solve your case but you will end up with 3 different tables. I think you want to use a single table with two or even three models so my advice is to try one of the STI library above.
STI is appropriate when your models have shared data/state. Shared behavior is optional because can be defined per Model. An example could be different type of vehicle Models: Car, Truck, Bike etc..
With Polymorphic Relations instead, a model can belong_to several models with a single association. This is useful when several models do not have a relationship or share data with each other, but have a relationship with the polymorphic class. An example could be the Comment Model that can belongs to other Models: User, Post, Image etc..

How to use multiple tables in one model?

How to add multiple tables in one model without creating new model.
Is this standard practice to use same in laravel-lumen.
Or should I create 50 models to work on 50 tables.
You can't use multiple table in one model. Each model is written for a specific table.
https://laravel.com/docs/5.7/eloquent#introduction
Laravel uses Eloquent Object Relational Mapper. So each model is like a class representation having methods to do query underneath.
You have to create 50 models if you have 50 tables, or at-least for the tables you are using in your application. TO save time, go for plugins like this which would generate eloquent models based on your database structure. Also check another plugin if it helps.
It's not possible.
Each table should have their own model. But it isn't necessary all the times to make a model for each table. Investing some time on making model will help a lot in future work.

Models responsability

I have a doub about Laravel. The models are used to define the relationships between the models like hasMany, belongsTo, etc. Also the models are used to define the fillable fields. But he models are only for that? Because I already check some examples that it seems that some queries are executed in the models instead of the controller so Im not understanding if the models should also have the querying of the relationships or not. Can you give a help to understand better what is the correct use of models (what should be placed in the models)?
Its same way to execute queries on model or controller. Written queries in model make your controller more clean. We can write mutator, accessor or query scope in eloquent model. Correct me if I'm wrong.
Visit https://laravel.com/api/5.5/Illuminate/Database/Eloquent/Model.html
You can refer this documentation, it's quite helpful if you want to know deep basics and responsibilities about particular part in Laravel.
Models are mostly used to make an outlook of the data i.e what fields are going to be saved in the database and we also use it to associate the relationships with other related data as you already know but we also use it to alter the values that are either going in/out of the data base which you can check in the documentation in link bellow https://laravel.com/docs/5.6/eloquent-mutators
the main purpose is to divide the code between controller and model (were it best fit to be)

Resources