Laravel Eloquent Relationships

Lesson 27 of 50 - Learn how to connect database tables using Laravel Eloquent relationships.

54%
1. What Are Eloquent Relationships?

Eloquent relationships allow Laravel models to retrieve related records from different database tables easily.

For example, consider a school database:

  • A student can have multiple assignments.
  • A student belongs to a course.
  • A student can have multiple fee payments.
  • A student and a course can have a many-to-many relationship.

The main relationship types are:

Relationship Meaning
One-to-One One record is associated with one other record.
One-to-Many One record can have multiple related records.
Many-to-One Multiple records belong to one record.
Many-to-Many Multiple records can be related to multiple records.
2. One-to-One Relationship

A one-to-one relationship means one record in a table is associated with one record in another table.

Example: One student has one student profile.

students table

id | name
1  | Rahul
2  | Priya

student_profiles table

id | student_id | address
1  | 1          | Patna
2  | 2          | Delhi

The student_id column connects the profile to its student.

Student.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasOne;

class Student extends Model
{
    public function profile(): HasOne
    {
        return $this->hasOne(StudentProfile::class);
    }
}

StudentProfile.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class StudentProfile extends Model
{
    public function student(): BelongsTo
    {
        return $this->belongsTo(Student::class);
    }
}

Retrieve the student's profile:

$student = Student::find(1);

echo $student->profile->address;

This assumes the student and profile records exist. If the profile may be missing, use $student->profile?->address.

3. One-to-Many Relationship

A one-to-many relationship means one record can have multiple related records.

Example: One student can submit multiple assignments.

students table

id | name
1  | Rahul

assignments table

id | student_id | title
1  | 1          | HTML Assignment
2  | 1          | CSS Assignment
3  | 1          | JavaScript Assignment

Student.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;

class Student extends Model
{
    public function assignments(): HasMany
    {
        return $this->hasMany(Assignment::class);
    }
}

Retrieve all assignments of a student:

$student = Student::find(1);

foreach ($student->assignments as $assignment) {
    echo $assignment->title . '<br>';
}

Laravel uses the student_id foreign key on the assignments table by convention.

4. Many-to-One Relationship

Many-to-one is the reverse side of a one-to-many relationship.

For example, many students may belong to one course. Each student record stores a course_id.

Student.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class Student extends Model
{
    public function course(): BelongsTo
    {
        return $this->belongsTo(Course::class);
    }
}

Retrieve a student's course:

$student = Student::find(1);

echo $student->course->course_name;

If a student may not have a course assigned, use $student->course?->course_name. The related model's field must match your database schema.

By default, belongsTo() expects a foreign key named course_id on the students table.

5. Many-to-Many Relationship

A many-to-many relationship means multiple records can be associated with multiple records.

Example:

  • A student can enroll in multiple courses.
  • A course can have multiple students.

This relationship uses an intermediate table called a pivot table.

course_student pivot table

student_id | course_id
1          | 1
1          | 2
2          | 1

Student.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;

class Student extends Model
{
    public function courses(): BelongsToMany
    {
        return $this->belongsToMany(Course::class);
    }
}

Course.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;

class Course extends Model
{
    public function students(): BelongsToMany
    {
        return $this->belongsToMany(Student::class);
    }
}

Retrieve courses for a student:

$student = Student::find(1);

foreach ($student->courses as $course) {
    echo $course->course_name . '<br>';
}

Laravel expects the pivot table to be named course_student by default, with course_id and student_id foreign keys. If your table is named differently, specify it in belongsToMany().

6. Create Related Records

Eloquent lets you create related records through relationship methods.

Create an assignment for a student:

$student = Student::findOrFail(1);

$student->assignments()->create([
    'title' => 'Laravel Assignment',
    'description' => 'Complete the Laravel basics exercises',
]);

The relationship automatically sets the student_id foreign key.

The Assignment model must allow the required fields through its $fillable property, and the assignments table must contain these columns.

Attach a course to a student:

$student = Student::findOrFail(1);

$student->courses()->attach(2);

The example attaches the course with ID 2. To avoid duplicate pivot records, use syncWithoutDetaching([2]) when appropriate.

7. Eager Loading Relationships

Eager loading retrieves related records along with the main records. It can help prevent unnecessary repeated database queries.

Without eager loading:

$students = Student::all();

foreach ($students as $student) {
    echo $student->course?->course_name;
}

Depending on the data and loaded relations, this can issue additional queries for individual students.

With eager loading:

$students = Student::with('course')->get();

foreach ($students as $student) {
    echo $student->course?->course_name;
}

Load multiple relationships:

$students = Student::with([
    'course',
    'assignments',
    'profile',
])->get();

Eager loading is especially useful on listing pages that display information from related tables.

8. Count Related Records and Filter Relations

Use withCount() to retrieve the number of related records without loading every related model.

Count assignments for each student:

$students = Student::withCount('assignments')->get();

foreach ($students as $student) {
    echo $student->name;
    echo ' - Assignments: ';
    echo $student->assignments_count;
}

Find students who have assignments:

$students = Student::has('assignments')->get();

Find students with at least three assignments:

$students = Student::has('assignments', '>=', 3)->get();

Load only matching assignments:

$students = Student::with([
    'assignments' => function ($query) {
        $query->where('title', 'like', '%Laravel%');
    },
])->get();

Relationship queries help you build student dashboards, course lists, assignment reports, and fee management pages.

9. Practical Assignment

Build a small school management module using Eloquent relationships.

  1. Create a students table and Student model.
  2. Create a student_profiles table with a student_id foreign key.
  3. Define a one-to-one profile relationship.
  4. Create an assignments table with a student_id foreign key.
  5. Define a one-to-many assignments relationship.
  6. Create a courses table and course_student pivot table.
  7. Define a many-to-many relationship between students and courses.
  8. Display each student's course and assignment details.
  9. Use eager loading to retrieve related data efficiently.
  10. Display the number of assignments using withCount().

Important:

  • Use migrations to create the tables and foreign keys.
  • Ensure relationship names match those used in your views and controllers.
  • Handle missing related records safely.
  • Validate user input before creating related records.
Quick Quiz

1. Which method defines a one-to-many relationship?




2. Which method defines a many-to-many relationship?




3. What is the purpose of eager loading?