Reputation: 2942
I have a database schema in my laravel app. In that schema, there are three models - Boss
, Employee
& Review
.
A Boss can have many employees. An Employee can have many bosses(we can consider bosses from previous jobs). An Employee can Review his/her Boss. Boss can't Review anyone, so only Employee can review.
Thus, there are these relationships -
Employee & Boss has many-to-many relationship
Employee & Review has one-to-many relationship ( one Employee can Review multiple Bosses, thus having multiple reviews from his/her side ).
As you can see there is no direct relationship between Boss
& Review
. But, the query is -
What are the reviews for Boss 'x'?
To answer this query in laravel, I first thought that it had 'hasManyThrough' relationship. But, 'hasManyThrough' works only when Boss & Employee have 'one-to-many' relationship. That is, when one Boss can have multiple Employee but not vice-versa.
So, my question is - Is there a relationship which is applicable in this scenario(like polymorphic etc.)? If yes, how to use it in laravel?
Upvotes: 0
Views: 906
Reputation: 81187
No need for that extra table with reviews.
Here's all you need - first the tables:
bosses: id, ...
employees: id, ...
boss_employee: id, boss_id, employee_id, review (nullable), ...
Then the models:
// Boss model
public function employees()
{
return $this->belongsToMany('Employee')->withPivot('review');
}
public function reviews()
{
return $this->hasMany('Review');
}
// Employee model
public function bosses()
{
return $this->belongsToMany('Boss')->withPivot('review');
}
public function reviews()
{
return $this->hasMany('Review');
}
// Review model
protected $table = 'boss_employee';
public function boss() // or eg. reviewed
{
return $this->belongsTo('Boss');
}
public function employee() // or eg. reviewer
{
return $this->belongsTo('Employee');
}
Now, with this setup you can do this:
// get boss and his review
$boss = $employee->bosses->first();
$review = $boss->pivot->review;
// get review for given boss of an employee
$review = $employee->reviews()->where('boss_id', $bossId)->first();
// get bosses with reviews
$bosses = Boss::whereHas('reviews', function ($q) {
$q->whereNotNull('review');
})->get();
// and so on and so forth
You can enhance your Review
model by adding global scope so it returns only the rows from boss_employee
table having not null
review field. This would be pretty much the same as SoftDeletingScope
, but the conditions need to be swapped - by default whereNotNull
, instead of whereNull
in the SoftDeletingScope.
Upvotes: 1