Laravel has one through
Laravel 5.8 is now released and one thing from the release notes many people might be waiting for is the hasOneThrough
relationship. Laravel ealier had hasManyThrough
, but with the addition of hasOneThrough
it's more flexible. Let's dive into an example :
Consider we have User
Model, Reviewer
Model and Activity
Model with structure :
users
id - integer
reviewer_id - integer
reviewers
id - integer
activities
id - integer
user_id - integer
Each reviewer
has one user
, and each user
is associated with one user activity
record. If we want to get activity
from reviewer
, there is no reviewer_id
column in activities
table, in such case we can use hasOneThrough
relation. Let's define the relationship now :
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Reviewer extends Model
{
/**
* Get the reviewer's activity.
*/
public function activity()
{
return $this->hasOneThrough('App\Activity', 'App\User');
}
}
To understand more, lets use Laravel conventional terms on the models. In this case the Activity
is the final model we would need to relate, while User
is the intermediate model.
As all other relationships in Laravel, we can also explicitely specify the foreign keys while definining hasOneThrough
relation, Let's do that for this example :
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Reviewer extends Model
{
/**
* Get the reviewer's activity.
*/
public function activity()
{
return $this->hasOneThrough(
'App\Activity',
'App\User',
'reviewer_id', // Foreign key on users table...
'user_id', // Foreign key on activities table...
'id', // Local key on reviewers table...
'id' // Local key on users table...
);
}
}
Now you can easily do :
$reviewer = Reviewer::first();
$activity = $reviewer->activity;