Laravel has many through Eloquent relationship tutorial
Laravel provides eloquent relationship which provides powerful query builders. In Laravel, eloquent relationships are defined in model classes. Laravel eloquent provides easy ways to create common relationships:
- one to one
- one to many
- many to many
- has one of many
- has one through
- has many through
- one to one polymorphic
- one to many polymorphic
- many to many polymorphic
In this article, we will discuss on Laravel's Has many through eloquent relationship. This is little complicated relationship than has one through relationship. In this relationship, one model has many associated model through intermediate model.
For example, a School
model may be associated with many Standard
model and Standard
model may be associated with many Student
model. In this relationship, a School
model doesn't have direct relationship with Student
model but through Standard
model.
Example:
Now, in this example, we will build relationship between School
and Student
through Standard
model so we can access All students of School.
We assume that you have created fresh Laravel application. We also assume that you have confiured database connection.
Database tables
In this relationship, we have three database tables: schools, standards and students.
Migration
we need to create three migration table. Run the following three commands into Terminal to create migration classes at database/migrations
directory.
php artisan make:migration create_schools_table
php artisan make:migration create_standards_table
php artisan make:migration create_students_table
Below are the migration table fields for these table:
schools migration
In the schools migration, we have defined the following fields:
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('schools', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
}
standards migration
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('standards', function (Blueprint $table) {
$table->id();
$table->integer('school_id');
$table->string('name');
$table->timestamps();
});
}
students migration
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('students', function (Blueprint $table) {
$table->id();
$table->integer('standard_id');
$table->string('name');
$table->timestamps();
});
}
Now run the migrate command to create tables into database.
php artisan migrate
Model
Laravel model located at app/Models
directory. Create model classes for these tables using following Artisan commands one by one into Terminal.
php artisan make:model School
php artisan make:model Standard
php artisan make:model Student
Now, let's look at the migration fields. We have school_id
field in the standards table and standard_id
in the students field. There is no direct relationship between schools and students table. To define relationship between schools and students table, create a method into School
model.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class School extends Model
{
use HasFactory;
/**
* Get all the students for the school.
*/
public function students()
{
return $this->hasManyThrough(Student::class, Standard::class);
}
}
In the hasManyThrough
method, first argument is the model that we want to access, the second argument is the intermediate model. Of course, you may define custom table fields instead of id of model name field.
/**
* Get the Student of Standard.
*/
public function student()
{
return $this->hasManyThrough(
Student::class,
Standard::class,
'school_id', // Foreign key on the standards table
'standard_id', // Foreign key on the students table
'id', // Local key on the schools table
'id' // Local key on the standards table
);
}
Route
In routes/web.php
file, we have added new route for relationship testing.
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\StudentController;
Route::get('/student', [StudentController::class, 'index']);
Controller
As we have added route, also create StudentController with following command.
php artisan make:controller StudentController
Open the controller at app/Http/Controllers/StudentController
and create index method. To retrieve all the students record for a School, access students attribute of School
model which we have created method.
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
$students = School::find(1)->students;
dd($students);
}
This will return all students record with the associated school_id
of 1. If the relationship not found, the eloquent will return null record.
I hope this will help you to understand has many through eloquent relationship.
Copyright 2023 HackTheStuff