Laravel Relationships - как запросить связать модели в 3х уровневый объект

В проекте на Laravel 8 - есть таблицы и модели: contractors(полные данные о враче или клинике), doctors(врачи), clinics(клиники), specializations(специализации) и services (услуги). Также есть таблицы связи clinic_doctors, doctors_services и doctors_specializations.

В моделях используется привязка моделей через ->with() и hasMany. Для получения например услуг у врача используется вот такая функция для with

protected $with = ['avatar', 'city'];

/**
 * Получить Город контрагента.
 */
public function city()
{
     return $this->belongsTo(Cities::class, 'cityID', 'id');
}

/**
* Получить Специализации контрагента.
*/
public function specializations()
{
    return $this
        ->hasMany(ContractorsSpecializations::class, 'contractorID', 'id')
         >join('specializations', 'contractors_specializations.specializationID', 'specializations.id');
}

/**
 * Получить Услуги контрагента.
 */
public function services()
{
   return $this
      ->hasMany(ContractorsServices::class, 'contractorID', 'id')
      ->join('services', 'contractors_services.serviceID', 'services.id');
}

/* Получение информации о клинике */
public static function getClinicInfo() {

    $contractor = self::where('contractors.deleted', false)
        ->where('contractors.id', $contractorID)
        ->join('clinics', 'contractors.id', 'clinics.contractorID')
        ->select(
            'clinics.id as clinicID',
            'clinics.fullName as clinicFullName',
            'clinics.shortName as clinicShortName',
            'clinics.headClinicID',
            'contractors.*',
        )
        ->with('specializations')
        ->with('services')
        ->with('doctors');
}

! Всё работает нормально, все данные подгружаются, но теперь необходимо собрать набор данных в следующем виде, а именно получить данные о клиниках, привязать специализации и услуги к клинике, найти врачей, которые привязаны к клинике и к врачам уже привязать уже их специализации и услуги.

{
    "clinicID":4,
    "contractorID": 1,
    "naming": "The big clinic naming",
    "city": {
        "id": 1,
        "name": "New-York"
    },
    "doctors": [
        {
            "id": 1,
            "contractorID": 2,
            "name": "Ivan",
            "surname": "Ivanov",
            "city": {
                "id": 2,
                "name": "Oslo"
            },
            "specializations": [
                {
                    "id": 2,
                    "name": "Лор",
                },
            ],
            "services": [],
        },
        {
            "id": 2,
            "contractorID": 3,
            "name": "Petr",
            "surname": "Ivanov",
            "city": {},
            "specializations": [
                {
                    "id": 1,
                    "name": "Хирург",
                },
            ],
            "services": [
                {
                    "id": 1,
                    "name": "Осмотр",
                },
            ],

        }

    ],
    "specializations": [
        {
            "id": 1,
            "name": "Хирург",
        },
        {
            "id": 2,
            "name": "Лор",
        },
        {
            "id": 3,
            "name": "Терапевт",
        }
    ],
    "services": [
        {
            "id": 1,
            "name": "Осмотр",
        },
        {
            "id": 2,
            "name": "Лечение",
        },
        {
            "id": 3,
            "name": "Анализы",
        }
    ],
}

Возможно ли сделать такое стандартными средствами или без циклов и переборов тут не обойтись? Заранее спасибо всем за помощь!


Ответы (1 шт):

Автор решения: Larvis

Проблема решилась, частично использовал ответы из статьи на англофоруме:

Добавил функции для with в связанные таблицы (ClinicsDoctors), менял название ключей:

В главной функции использовал следующую конструкцию:

->with(['doctors.services', 'doctors.specializations'])

Вопрос и ответ ENG

→ Ссылка