I have a laravel project where a User
can have many Client
class. The Client
can have many Session
and and a Session
can have many Assessment
and many Plan
. I am using hasManyThrough on the Client
to get Assessment
and Plan
. Each Assessment
and Plan
has a review_date
timestamp saved into the database.
What I'd like to do is get all the Assessment
and Plan
for any Client
with their review_date
as today. Ideally something like:
$events = Auth::user()->reviews()->today();
What I don't know how to do it make the reviews
function, because it's essentially combining 2 relationships.
Can anyone help me out?
User.php
public function clients()
{
return $this->hasMany(Client::class);
}
public function assessments()
{
return $this->hasManyThrough(Assessment::class, Client::class);
}
public function plans()
{
return $this->hasManyThrough(Plan::class, Client::class);
}
public function reviews()
{
// return all assessments and plans
}
public function scopeToday(Builder $query)
{
$query->whereDate('review_date', Carbon::today());
}
Client.php
public function assessments()
{
return $this->hasManyThrough(Assessment::class, Session::class);
}
public function plans()
{
return $this->hasManyThrough(Plan::class, Session::class);
}
Session.php
public function assessments()
{
return $this->hasMany(Assessment::class);
}
public function plans()
{
return $this->hasMany(Plan::class);
}
CodePudding user response:
Reverse chaining is better here. Declare a reverse relationship and build a query.
Plan::query()->whereHas('session', function($q) {
$q->whereHas('client', function($q) {
$q->where('user_id', Auth::id())
})
});
CodePudding user response:
You can get a collection from both methods, so you could simply merge the 2 together. (Be warned, this will lead to ugly code later when you have to check object types during the loop.) You can't chain the scope method, since you aren't getting back a relationship object, buy you could pass the date as a parameter instead, or just fix it at today if you'll never need other dates.
public function reviews(Carbon $date)
{
return $this
->assessments()
->whereDate('review_date', $date)
->get()
->merge(
$this->plans()->whereDate('review_date', $date)->get()
)
->sortBy('review_date');
}
And then call it like this:
$date = now();
$events = Auth::user()->reviews($date);