Home > other >  Laravel use model property in relation method
Laravel use model property in relation method

Time:06-08

I have relation method for a model which has a comparison on a property(created_at) of the model itself. Where I want to compare the created_at date of the 'Appointment' model with the created_at of the 'Treatment'. I only want a 'Treatment' if its 'created_at' date is later than that of the 'Appointment'

AppointmentController.php

public function index(): JsonResource
{
    $users = User::with([
        'appointment' => function ($query) {
            $query->with(['appointment_events']);
        },
    ])
        ->active()
        ->get();
    
    return UserResource::collection($users);
}

Appointment.php

public function appointment_events(): HasMany
{
    return $this->hasMany(AppointmentEvent::class)
        ->with([
            'customer' => function ($query) {
                $query->with([
                    'section' => function ($subquery) {
                        $subquery
                            ->with([
                                'advice',
                                'treatment' => function ($subquery) {
                                  $subquery->where('created_at', '>', blank); //How can I get the model's created_at date.
                                },
                            ]);
                    },
                ]);
            },
        ]);
}

Is there a way to do this?

CodePudding user response:

If I understand yours relations are

User ->HasManyAppointments ->HasManyAppointmentsEvents.

You can access quite directly to appointments events data from a user

namespace App\Models;
 
use Illuminate\Database\Eloquent\Model;
 
class User extends Model
{
    /**
     * Get all of the appointment_events for the user.
     */
    public function appointment_events()
    {
        return $this->hasManyThrough(Appointment::class, AppointmentEvent::class);
    }
}

From Laravel Doc: Has Many Through

So you can query

$collection = User::with(['appointments','appointment_events'])->where()->get();

which give you all appointments and related appointment_events on a particular user. and you can tap on that collection or filter or whatever business logic you want.

CodePudding user response:

I think you should move the query to a scope on Appointment model and keep the relationship definition simple.

Note: Below assumes table names and column names as per standard Laravel conventions. If you have different convention, please modify the table names and column names accordingly.

class Appointment extends Model
{
    public function scopeWithFutureTreatments($query)
    {
        return $query->with([
            'appointment_events' => function($query) {                
                $query->with([
                    'customers' => function($query) {
                        $query->with([
                            'section' => function($query) {
                                $query->with([
                                    'advice',
                                    'treatment' => function($query){
                                        $query->join('sections', 'section.id', '=', 'treatments.section_id')
                                            ->join('customers', 'customers.id', '=', 'sections.customer_id')
                                            ->join('appointment_events', 'appointment_events.id', '=', 'customer.appointment_events_id')
                                            ->join('appointments', 'appointments.id', '=', 'appointment_events.appointment_id')
                                            ->whereColumn('treatments.created_at', '>', 'appointments.created_at')
                                            ->select('treatments.*')
                                    }
                                ]);
                            }
                        ]);
                    }
               ]);
            }
        ]);
    }

    public function appointment_events(): HasMany
    {
        return $this->hasMany(AppointmentEvent::class);
    }
}

Then in AppointmentController the following should get you the desired results

public function index(): JsonResource
{
    $users = User::with([
        'appointment' => function ($query) {
            $query->withFutureTreatments();
        },
    ])
    ->active()
    ->get();
    
    return UserResource::collection($users);
}
  • Related