Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

DivDax's avatar
Level 10

getManyThrough with manyToMany

Hi,

i'm a bit confused with relations and need your help.

I need to know which services a user has claimed through his appointments

client has many appointments
appointments belongs to clients
appointments belongs to many services
services belongs to many appointments
0 likes
11 replies
DivDax's avatar
Level 10

@codeatbusiness this not working because appointments belongs to many services:

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'services.appointment_id' in 'on clause' (SQL: select `services`.*, `appointments`.`client_id` from `services` inner join `appointments` on `appointments`.`id` = `services`.`appointment_id` where services.account_id = '1' and `appointments`.`client_id` = 1)
xingfucoder's avatar

Then you need to make a many to many relationship between Services and Appointments with the related pivot table and I would make another hasManyThrough as follow:

class Client extends \Eloquent {

    public function appointments()
    {
        return $this->hasManyThrough('Appointment', 'Service');
    }
}

Hope it helps you.

DivDax's avatar
Level 10

@codeatbusiness this also isn't working because hasManyThrough is using 3 tables? I've 4.

clients
appointments
appointment_service
services
xingfucoder's avatar

The appointment_service pivot table should be used by the many-many relationship between appointments and services, and the way to access to appointments or services would be each of both tables using the hasManyThrough, I think.

Could you put the code that you are using within your models here?

DivDax's avatar
Level 10

Hmm, very confusing to me... This is what i got so far:

class Client extends Model {
 public function appointments()
 {
  return $this->hasMany('Appointment');
 }

 public function treatments()
 {
  return $this->hasManyThrough('Service','Appointment');
 }
}
class Appointment extends Model {
 public function client()
 {
  return $this->belongsTo('Client');
 }

 public function services()
 {
  return $this->belongsToMany('Service');
 }
}
class Service extends Model {
 public function appointment()
 {
  return $this->belongsToMany('Appointment');
 }
}

treatments() in my Client should return all treatments (grouped) through his appointments.

Ghunti's avatar

I was also having the same problem but then I realized that I was not using the nested relations:

$books = Book::with('author.contacts')->get();

Maybe in your case something like:

Client::with('appointments.services')->get();

This will eager load all the client appointments and linked services

4 likes
sgelbart's avatar

For my project I had user, clubs, user_clubs, and user_club_badges. I originally created user_clubs as a pivot and I totally regret it. There's a way to do a triple pivot but I don't totally trust it and I have lots of functionality attached to this whole process so ultimately I'm thinking the best approach is to make a model called UserClub (or Memberships).

Using this approach it's trickier to do $club->users (you can I think but it's harder). Instead focus on doing $club->memberships (then foreach membership do $membership->user->id).

I've been waiting for a good solution for this, while there may be another one I wanted to share mine incase anyone else had the same frustrations. Save yourself the headache and don't use pivots for anything complex!!

kfirba's avatar

@DivDax You may want something like this (I have seen it somewhere before, just can't recall where):

Client::with(['appointments.services' => function($query) use (&$services) {
    $services = $query->get()->unique();
}]);

// $services will now be all the services for the client.
return $services;

Please or to participate in this conversation.