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);
