RafaelMunoznl's avatar

Allow to load relations in an infinite circle: $appointment->client->appointments

I have the following model structure:

  • Appointment hasOne Client
  • Client hasMany Appointments

Now I have a calendar with all appointments foreach($appointments as $appointment)

  • Appointment10 (client 1)
  • Appointment11 (client 2)
  • Appointment 09 (client1)
  • etc

When I click on one of the coming appointments I open a modal (no a new view). That makes me to load all the data of each appointment in advance which I recognize is a huge performance stress, but it is a better UX.

The point here is that now in the Appointment details modal, I want to show all the appointments that the client has in the pass. His history: like this:

- Appointment 10 (February2020)
    - Client 1
        - Appointment 3 (December 2019)
        - Appointment 4 (November 2019)
        - Appointment 5 (October 2019)


In the modal I do this:

    {{ $appointment->client->full name }}

    foreach($appointment->client->appointments as $clientAppointments)
    {
        {{ $clientAppointment->date }} // December 2019
        {{ $clientAppointment->time }}
        {{ $clientAppointment->notes }}
    }

And I get an error:

Trying to get attribute of non object

It seems like Laravel does not allows to load an almost “infinite circle” here:


$appointment->client->appointments

Is there any way to tell Laravel, that I need at least this one more level down of relations?

0 likes
4 replies
tisuchi's avatar

@rafaelmunoznl

If I understand you correctly, you can do a reverse relationship.

For example-

  • Client hasMany Appointments
  • Appointment belongs to a Client

Now can easily access all the appointments from a client.

$client->appointments;

In the reverse way-

$appointments->client;
RafaelMunoznl's avatar

@tisuchi that's the way it is if you make two different calls.

$appointments->clientwill give you a collection like this:

  • Appointment1
    • Client1
  • Appointment 4
    • Client2

$client->appointments;will give back following collection structure:

  • Client1
    • Appointment2
    • Appointment3
  • Client2
    • Appointment4
    • Appointment4

But what I need here is to get a Collection with one level deeper

  • Appointment1
    • Client1
      • Appointment2
      • Appointment3
  • Appointment 4
    • Client2
      • Appointment 4
      • Appointment5

Something like: $appointment->client->appointments but this results in a kind of circle and the second level is never load

tisuchi's avatar

@rafaelmunoznl

I can understand your logic.

But I really not understand why you are trying to reverse back to the relationship.

You better show you relationships in the models, controller and views code.

RafaelMunoznl's avatar

Client.php

    public function appointments()
    {
        return $this->hasMany('App\Appointment')->orderBy('startDateTime', 'DESC');
    }

Appointment.php

    public function client()
    {
        return $this->belongsTo('App\Client'); 
    }

AppointmentsController

public function index(Company $company)
    {
    …
        $appointments = Appointment::where('company_id', $company->id)->get();
        …

        return view('appointments.index', compact('appointments'));
    }

Index.view

foreach( $appointments as $appointment)
{
    {{ $appointment->client->fullname }}
    {{ $appointment->date }} 
            {{ $appointment->time }}
            {{ $appointment->notes }}

    <h3>Previous appointments</h3>
        foreach($appointment->client->appointments as $clientAppointments)
        {
                {{ $clientAppointment->date }} 
                {{ $clientAppointment->time }}
                {{ $clientAppointment->notes }}
        }
}

I get the error: Trying to get attribute of non object in the second foreach. clients->appointments does not work as a second level

Please or to participate in this conversation.