laraveleager-loading

Laravel using eager loading instead of making 3 queries


I am trying to improve at laravel, the story here is that I have customers, customers can have appointments and users create appointments for the customers.

Visit model:

class Visit extends Model
{
    use HasFactory;

    protected $fillable = [
        'user_id',
        'customer_id',
        'report',
        'appointment_date',
        'appointment_time',
    ];

    protected $dates = ['appointment_date'];

    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }

    public function customer(): BelongsTo
    {
        return $this->belongsTo(Customer::class);
    }

Customer model:

class Customer extends Model
{
    use HasFactory;

    protected $fillable = [
        'name',
        'city',
        'address',
        'email_address',
        'phone_number',
    ];

I have a script that checks if the customer should have a new appointment (this happens if there is no new appointment in the future and when the last appointment is longer than 5 months ago or there is no appointment yet:

$customers = Customer::get();
foreach ($customers as $customer) {
    $Newvisit = $customer->visits()->whereInFuture()->first();
    // continue if the customer already has an appointment planned in the future
    if ($Newvisit !== null) {
        continue;
    }

    // This also retrieves visits with null appointment date, this is neccesary for appointments that are not schedulded but already planned
    $lastVisit = $customer->visits()->OrderBy('appointment_date', 'desc')->first();
    // Customer has no visits yet
    if ($lastVisit === null) {
        $this->createNewAppointment($customer);
        continue;
    }

    $lastVisitDate = new Carbon($lastVisit->appointment_date);
    // Last appointment for customer is longer than .. months ago
    if ($lastVisitDate->diffInMonths() > $this->argument('months')) {
        $this->createNewAppointment($customer);
        continue;
    }
}

Is there a way to use eager loading to only run 1 query? or is this impossible since I need to retrieve a new visit and last visit


Solution

  • There is a relationship in customer model to get visits.

    public function visits()
    {
        return $this->hasMany(Visit::class);
    }
    

    Then you can fetch customers data as $customers = Customer::with('visits')->get();

    Or you can order visits like this -

    $customers = Customer::with(['visits' => function ($query) {
      $query->orderBy('appointmemt_date', 'desc');
    }])->get();
    

    Then $customer->visits->first(); may give you inkling whether it is New visit or Last Visit.