Has Many Through

What is Has Many Through?

A Has Many Through relationship is used when one model is related to many records of another model through an intermediate model.

👉 Example:

  • A Hospital has many Patients.
  • But Patients are not directly linked to Hospital.
  • Instead, they are linked through Doctors (because each Doctor belongs to a Hospital and has Patients).

So the connection looks like:

 Hospital → Doctors → Patients

Flow diagram


Migration:

Use this command to generate a migration for creating a tables:

php artisan make:migration create_has_many_through_tables


Migration File

public function up(): void
{
    // Hospitals table
    Schema::create('hospitals', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->timestamps();
    });

    // Doctors table
    Schema::create('doctors', function (Blueprint $table) {
        $table->id();
        $table->foreignId('hospital_id')->constrained()->onDelete('cascade');
        $table->string('name');
        $table->timestamps();
    });

    // Patients table
    Schema::create('patients', function (Blueprint $table) {
        $table->id();
        $table->foreignId('doctor_id')->constrained()->onDelete('cascade');
        $table->string('name');
        $table->timestamps();
    });
}

public function down(): void
{
    Schema::dropIfExists('patients');
    Schema::dropIfExists('doctors');
    Schema::dropIfExists('hospitals');
}


Run Migration

php artisan migrate

Tables

hospitals table
id name created_at updated_at
doctors table
id name hospital_id created_at updated_at
patients table
id name doctor_id created_at updated_at
  • doctors.hospital_id is a foreign key referencing hospitals.id.
  • patients.doctor_id is a foreign key referencing doctors.id.

Model:

Generate a model with Artisan:

php artisan make:model Hospital
php artisan make:model Doctor
php artisan make:model Patient

This generates 3 files Hospital.php , Doctor.php and Patient.php


 Hospital.php 

namespace App\Models;

use App\Models\Doctor;
use App\Models\Patient;
use Illuminate\Database\Eloquent\Model;

class Hospital extends Model
{
    protected $fillable = ['name'];

    // HasManyThrough: Hospital → Doctors → Patients
    public function patients()
    {
        return $this->hasManyThrough(
            Patient::class,   // Final model
            Doctor::class,    // Intermediate model
            'hospital_id',    // Foreign key on doctors
            'doctor_id',      // Foreign key on patients
            'id',             // Local key on hospitals
            'id'              // Local key on doctors
        );
    }

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


Doctor.php

namespace App\Models;

use App\Models\Patient;
use App\Models\Hospital;
use Illuminate\Database\Eloquent\Model;

class Doctor extends Model
{
    protected $fillable = ['name', 'hospital_id'];

    public function hospital()
    {
        return $this->belongsTo(Hospital::class);
    }

    public function patients()
    {
        return $this->hasMany(Patient::class);
    }
}


Patient.php

namespace App\Models;

use App\Models\Doctor;
use Illuminate\Database\Eloquent\Model;

class Patient extends Model
{
    protected $fillable = ['name', 'doctor_id'];

    public function doctor()
    {
        return $this->belongsTo(Doctor::class);
    }
}

CRUD Examples

Create

use App\Models\Patient;
use App\Models\Hospital;
use App\Models\Doctor;

// Create a Hospital
$hospital = Hospital::create(['name' => 'City Care']);

// Create Doctor under Hospital
$doctor = Doctor::create([
    'hospital_id' => $hospital->id,
    'name' => 'Dr. John'
]);

// Assign Patient to Doctor
$patient = Patient::create([
    'doctor_id' => $doctor->id,
    'name' => 'Alice'
]);
Output
hospitals table
id name created_at updated_at
1 City Care 2025-08-25 14:55:55 2025-08-25 14:55:55
doctors table
id name hospital_id created_at updated_at
1 Dr. John 1 2025-08-25 14:55:55 2025-08-25 14:55:55
patients table
id name doctor_id created_at updated_at
1 Alice 1 2025-08-25 14:55:55 2025-08-25 14:55:55

Read (Get Related Data)

use App\Models\Patient;
use App\Models\Hospital;
use App\Models\Doctor;

// Get Hospital's Doctors 
$hospital = Hospital::find(1);
foreach ($hospital->doctors as $doctor) {
  echo $doctor->name;
}

// Get Hospital's Patients through Doctors
$hospital = Hospital::find(1);
foreach ($hospital->patients as $patient) {
  echo $patient->name;
}

// Get Doctor with Patients
$doctor = Doctor::find(1);
foreach ($doctor->patients as $patient) {
  echo $patient->name;
}

Update (Modify Data)

use App\Models\Patient;
use App\Models\Hospital;
use App\Models\Doctor;

// Update Patient 
$salary = Patient::where('doctor_id', 1)->first();
$salary->update(['name' => 'kenny']);

// Or directly
$hospital = Hospital::find(1);
$hospital->patients()->where('id', 1)->update(['name' => 'Alice Updated']);



Delete (Remove Data)

use App\Models\Patient;
use App\Models\Hospital;
use App\Models\Doctor;

// Delete Patient
$patient = Patient::first();
$patient->delete();

// Delete Patient via Doctor using hasMany
$doctor = Doctor::first();
$doctor->patients()->where('id', 1)->delete();

// Delete Doctor (will cascade Patients also if set cascade)
$doctor = Doctor::first();
$doctor->delete();

// Delete Hospital (cascade removes Doctors & their Patients)
$hospital = Hospital::first();
$hospital->delete();

Eager loading (optimizes queries)

use App\Models\Patient;
use App\Models\Hospital;
use App\Models\Doctor;

// Get Hospital's Doctors 
$hospital = Hospital::with('doctors')->find(1);
foreach ($hospital->doctors as $doctor) {
  echo $doctor->name;
}

// Get Hospital's Patients through Doctors
$hospital = Hospital::with('patients')->find(1);
foreach ($hospital->patients as $patient) {
  echo $patient->name;
}

// Get Doctor with Patients
$doctor = Doctor::with('patients')->find(1);
foreach ($doctor->patients as $patient) {
  echo $patient->name;
}

Always use with() when fetching related data in bulk.


Whereisstuff is simple learing platform for beginer to advance level to improve there skills in technologies.we will provide all material free of cost.you can write a code in runkit workspace and we provide some extrac features also, you agree to have read and accepted our terms of use, cookie and privacy policy.
© Copyright 2024 www.whereisstuff.com. All rights reserved. Developed by whereisstuff Tech.