Home > Mobile >  Laravel retrieve multiple relationships
Laravel retrieve multiple relationships

Time:12-05

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