Reputation: 39
I am trying to model a company and its relevant employee strucutre. I have 3 tables (company, position, employee) as below, and company haveMany position, and employee haveMany position. Position belongs to company, and position belongs to employee.
However, different position have some common field like onboard date, but have some fields are different. Forexmaple, CEO has a gurantee employment period, while other position dont. Quite a number of field is different too for different position.
In that case, should I using polymorphic to model? but as the company has quite a number of different position, this will create quite a lot new table in the database.
Do you have any advice on how to model different positions?
Companies
Positions
Employees
Upvotes: 1
Views: 253
Reputation: 7111
In that case, should I using polymorphic to model? but as the company has quite a number of different position, this will create quite a lot new table in the database.
No, why would be?
First of all, it should be manyToMany relation and not oneToMany because if you have two companies both of those can have CEO (for example) position and if you set $position->belongsTo(Company::class); it couldn't work.
It is polymorph relation there with positions
as polymorphic angle of that triangle.
You would need
// companies
id
name
// employees
id
name
// positions
id
name
// positionables
position_id
positionable_id
positionable_type
With this, your models would be
class Company extends Model
{
public function positions()
{
return $this->morphToMany(Position::class, 'positionable');
}
}
class Employee extends Model
{
public function positions()
{
return $this->morphToMany(Position::class, 'positionable');
}
}
class Position extends Model
{
public function companies()
{
return $this->morphedByMany(Company::class, 'positionable');
}
public function employees()
{
return $this->morphedByMany(Company::class, 'positionable');
}
}
It allows you to set positions, companies and employees separately. Meaning, From dashboard you can make some new positions that will be available on frontend from select options let's say. Of course you should allow company and to employee to create new position (I suggest) and not just to use existing one but it could be out of scope of this question now: in example, when (and if) company creates new position (instead of selecting existing ones from options list), you would first create that position and store it into positions
table and then associate company with it. Also, when using this kind of chained inputs to DB don't forget to use DB transactions. Into positionables
table you would set other fields important for each relation (onboard_date
, ceased_date
, etc).
Documentation is very good and consult it if something is not clear (I hope it is already).
Disclaimer: I don't know rest of your project business plan and rest of project's requirements but for these three entities this is the best structure you can go with. I have set just mandatory members to models and tables for this example. Also in offered answer, I presumed use of Laravel's naming convention that's blindly followd from docs and this repo.
Upvotes: 1
Reputation: 715
If the fields have no relationship with other tables, one possible way is to have a key-value table to store those fields and values:
position_fields
- id
- position_id
- key
- value
You can hence store the fields in key
and the respective value in value
. Then you may overwrite the __get
magic method in Position
model e.g.
public function __get($key){
$position_field = $this->hasMany(PositionField::class)->where('key', $field)->first();
return !!$position_field ? $position_field->value : $this->getAttribute($key);
}
Upvotes: 0