通过多对一和多对多创建 Laravel 关系

Create Laravel Relationship through Many-To-One and Many-To-Many

我在定义多个模型之间的关系时遇到问题。 在 Laravel 文档中,我能够找到一个 hasManyThrough() 关系,其中关系通过两个多对一模型向下扩展,但我的多对一模型存在问题然后是多对多关系。这是 tables:

practices
  id
  name

locations
  id
  practice_id
  name

doctors
  id
  name

doctor_location
  doctor_id
  location_id

如您所见,实践可以有多个位置,而位置只能属于一个实践。医生可以有很多地点,而地点可以有很多医生。但是,我不确定如何向下钻取以创建 $practice->doctors 关系。我确实尝试了实践模型中的 hasManyThrough() 关系:

public function doctors() {
  return $this->hasManyThrough(Doctor::class, Location::class);
}

但这只是在医生 table 中查找 location_id 时引发了 sqlstate 错误。是否可以关联这些模型?

编辑:SQLState 错误

Illuminate\Database\QueryException
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'doctors.location_id' in 'on clause' (SQL: select `doctors`.*, `locations`.`practice_id` as `laravel_through_key` from `doctors` inner join `locations` on `locations`.`id` = `doctors`.`location_id` where `locations`.`practice_id` = 1)

我认为您的情况不需要医生和诊所之间有任何关系。以下查询应该有效:

Practice::with('locations.doctors');

输出应该是一个位置数组,每个位置都包含医生。

错误信息和documentation很清楚。 hasManyThrough 关系仅适用于 一对多 关系

Practices -> Locations一对多 Locations -> Doctors 多对多 在位置和医生之间有一个枢轴点 table。因此在这种情况下你不能使用 hasManyThrough

如果您真的想使用 hasManyThrough,您必须将 Locations -> Doctors 关系转换为 一对多 ,方法是放置location_id医生table

否则,只有像@Bulent 建议的那样才能得到医生

$practice = Practice::where("id", your_id )->with('locations.doctors')->first();

然后迭代思想位置和医生

foreach ($practice->locations as $location) {
    foreach ($location->doctors as $doctor) {
        // do stuff with each doctor here
    }
}

如您在错误中所见

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'doctors.location_id'

执行的查询试图在 doctorslocations 之间执行连接 tables

select `doctors`.*, `locations`.`practice_id` as `laravel_through_key` from `doctors` inner join `locations` on `locations`.`id` = `doctors`.`location_id` where `locations`.`practice_id` = 1)

查询使用此子句执行连接

inner join `locations` on `locations`.`id` = `doctors`.`location_id`

由于您 doctors table 没有 location_id 属性,这是导致该错误的主要原因。

这个错误是因为你用错误的模型定义了hasManyThrough关系,应该是这样的

public function doctors() {
    return $this->hasManyThrough(Doctor::class, DoctorLocation::class);
}

这假设您已经定义了一个模型 DoctorLocation,它引用了 doctor_location table。这将允许您从 Practice

访问医生

这将允许 eloquent 在 PracticeDoctor 之间执行 join 通过 doctor_location table 因为它有 location_iddoctor_id 属性。