Laravel Relationship: Student, Major, dan Subject
Dibuat : 25 Mei 2026
Repository GitHubDalam membangun aplikasi web yang scalable dengan Laravel, salah satu aspek terpenting adalah kemampuan untuk mengelola hubungan antar data (relationship) dengan baik. Database relasional modern memerlukan pendekatan yang terstruktur untuk menghubungkan berbagai entitas sehingga integritas dan konsistensi data tetap terjaga.
Laravel menyediakan fitur Eloquent ORM (Object-Relational Mapping) yang powerful untuk memetakan hubungan tabel database ke dalam bentuk objek yang mudah digunakan. Melalui pendekatan ini, developer tidak perlu menulis query SQL yang rumit, cukup dengan mendefinisikan method relasi di dalam Model.
Praktikum ini bertujuan memahami dan mengimplementasikan dua jenis relasi fundamental yaitu One-to-Many dan Many-to-Many melalui studi kasus sistem akademik yang menghubungkan data program studi (Major), mahasiswa (Student), dan mata kuliah (Subject).
attach(), sync() untuk
mengelola relasi Many-to-Many.Relationship atau relasi adalah hubungan antar tabel dalam database yang digunakan untuk menghubungkan data secara logis dan menjaga integritas referensial.
hasMany(),
belongsTo(), dan belongsToMany(),
developer dapat mendefinisikan relasi antar model tanpa query SQL manual.
with() untuk memuat relasi
bersamaan dengan data utama dalam satu query,
mengurangi beban database secara signifikan.
attach() digunakan
untuk menambahkan relasi baru, sedangkan sync() digunakan untuk
sinkronisasi relasi dengan
menghapus yang tidak ada dalam array baru dan menambahkan yang baru.
1. Persiapan Project dan Database
Melanjutkan project laravel dari praktikum 7. Buka file .env dan pastikan
konfigurasi detail koneksi
database sesuai:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=example_app
DB_USERNAME=root
DB_PASSWORD=
2. Membuat Migration File untuk Tabel Majors
Langkah pertama adalah membangun struktur tabel untuk program studi (Majors). Buat migration file baru:
php artisan make:migration create_majors_table
Buka file migration yang baru dibuat di database/migrations dan isi dengan
skema tabel majors:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up()
{
Schema::create('majors', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('majors');
}
};
Tabel majors memiliki kolom id sebagai primary key, name untuk menyimpan nama program studi, serta timestamps untuk mencatat waktu pembuatan dan perubahan data.
3. Membuat Migration File untuk Tabel Students
Selanjutnya buat migration file untuk tabel mahasiswa dengan relasi One-to-Many ke tabel majors:
php artisan make:migration create_students_table
Isi file migration students dengan kode berikut yang menyertakan foreign key ke tabel majors:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up()
{
Schema::create('students', function (Blueprint $table) {
$table->id();
$table->string('nim')->unique();
$table->string('name');
$table->text('address');
$table->foreignId('major_id')->constrained('majors')->onDelete('cascade');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('students');
}
};
Pada tabel students, kolom major_id berfungsi sebagai foreign key yang
mereferensi tabel majors.
Pengaturan onDelete('cascade') memastikan ketika satu program studi
dihapus, semua mahasiswa
di program studi tersebut akan terhapus otomatis.
4. Membuat Migration File untuk Tabel Subjects
Buat migration file untuk tabel mata kuliah:
php artisan make:migration create_subjects_table
Isi file migration subjects dengan skema yang menyimpan data mata kuliah:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up()
{
Schema::create('subjects', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->integer('sks');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('subjects');
}
};
Tabel subjects menyimpan nama mata kuliah dan jumlah kredit (SKS). Tabel ini akan terhubung dengan tabel students melalui relasi Many-to-Many.
5. Membuat Migration File untuk Tabel Pivot Student_Subject
Untuk mendukung relasi Many-to-Many, buat tabel perantara (pivot table) yang menghubungkan students dan subjects:
php artisan make:migration create_student_subject_table
Isi file migration dengan struktur pivot table:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up()
{
Schema::create('student_subject', function (Blueprint $table) {
$table->id();
$table->foreignId('student_id')->constrained('students')->onDelete('cascade');
$table->foreignId('subject_id')->constrained('subjects')->onDelete('cascade');
$table->timestamps();
// Mencegah kombinasi student_id dan subject_id yang sama tersimpan lebih dari sekali
$table->unique(['student_id', 'subject_id']);
});
}
public function down()
{
Schema::dropIfExists('student_subject');
}
};
Tabel pivot ini menyimpan dua foreign key yang mereferensi students dan subjects. Constraint unique mencegah seorang mahasiswa terdaftar pada mata kuliah yang sama berkali-kali.
Setelah semua migration file dibuat, jalankan perintah migrate untuk membuat tabel di database:
php artisan migrate
6. Membuat Model dengan Definisi Relationship
Buat Model Major dengan method relasi ke Student:
php artisan make:model Major
Buka file app/Models/Major.php dan definisikan relasi One-to-Many:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
class Major extends Model
{
protected $fillable = ['name'];
public function students(): HasMany
{
return $this->hasMany(Student::class);
}
}
Buat Model Student dengan method relasi ke Major dan Subject:
php artisan make:model Student
Isi app/Models/Student.php dengan definisi kedua relasi:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
class Student extends Model
{
protected $fillable = ['nim', 'name', 'address', 'major_id'];
public function major(): BelongsTo
{
return $this->belongsTo(Major::class);
}
public function subjects(): BelongsToMany
{
return $this->belongsToMany(Subject::class);
}
}
Buat Model Subject dengan method relasi ke Student:
php artisan make:model Subject
Isi app/Models/Subject.php:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
class Subject extends Model
{
protected $fillable = ['name', 'sks'];
public function students(): BelongsToMany
{
return $this->belongsToMany(Student::class);
}
}
7. Membuat Seeder untuk Data Dummy
Buat seeder untuk program studi:
php artisan make:seeder MajorSeeder
Isi database/seeders/MajorSeeder.php:
<?php
namespace Database\Seeders;
use App\Models\Major;
use Illuminate\Database\Seeder;
class MajorSeeder extends Seeder
{
public function run()
{
$majors = [
'Teknik Informatika',
'Sistem Informasi',
'Teknik Komputer',
'Keamanan Siber'
];
foreach ($majors as $major) {
Major::create(['name' => $major]);
}
$this->command->info('Major seeder berhasil dijalankan');
}
}
Buat seeder untuk mata kuliah:
php artisan make:seeder SubjectSeeder
Isi database/seeders/SubjectSeeder.php:
<?php
namespace Database\Seeders;
use App\Models\Subject;
use Illuminate\Database\Seeder;
class SubjectSeeder extends Seeder
{
public function run()
{
$subjects = [
['name' => 'Pemrograman Web', 'sks' => 3],
['name' => 'Basis Data', 'sks' => 3],
['name' => 'Algoritma dan Struktur Data', 'sks' => 4],
['name' => 'Jaringan Komputer', 'sks' => 3],
['name' => 'Sistem Operasi', 'sks' => 3],
['name' => 'Keamanan Informasi', 'sks' => 3]
];
foreach ($subjects as $subject) {
Subject::create($subject);
}
$this->command->info('Subject seeder berhasil dijalankan');
}
}
Buat seeder untuk mahasiswa yang lebih kompleks:
php artisan make:seeder StudentSeeder
Isi database/seeders/StudentSeeder.php:
<?php
namespace Database\Seeders;
use App\Models\Student;
use App\Models\Subject;
use Illuminate\Database\Seeder;
class StudentSeeder extends Seeder
{
public function run()
{
$students = [
['nim' => '2411533001', 'name' => 'Ahmad Rizki', 'address' => 'Jalan Merpati No. 5', 'major_id' => 1],
['nim' => '2411533002', 'name' => 'Budi Santoso', 'address' => 'Jalan Anggrek No. 10', 'major_id' => 1],
['nim' => '2411533003', 'name' => 'Citra Dewi', 'address' => 'Jalan Melati No. 7', 'major_id' => 2],
['nim' => '2411533004', 'name' => 'Doni Hermawan', 'address' => 'Jalan Mawar No. 3', 'major_id' => 2],
['nim' => '2411533005', 'name' => 'Eka Putri', 'address' => 'Jalan Dahlia No. 8', 'major_id' => 3],
];
foreach ($students as $studentData) {
$student = Student::create($studentData);
// Assign mata kuliah secara random (2-4 mata kuliah per mahasiswa)
$subjects = Subject::inRandomOrder()->take(rand(2, 4))->pluck('id');
$student->subjects()->attach($subjects);
}
$this->command->info('Student seeder berhasil dijalankan');
}
}
Daftarkan ketiga seeder di database/seeders/DatabaseSeeder.php:
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
public function run()
{
$this->call([
MajorSeeder::class,
SubjectSeeder::class,
StudentSeeder::class,
]);
}
}
Jalankan seeder untuk mengisi database dengan data dummy:
php artisan db:seed
8. Membuat Controller untuk Mengelola Data Relasi
Buat controller untuk menampilkan data mahasiswa dengan relasi:
php artisan make:controller StudentController
Buka app/Http/Controllers/StudentController.php dan implementasikan method
index dengan eager loading:
<?php
namespace App\Http\Controllers;
use App\Models\Student;
use App\Models\Major;
use App\Models\Subject;
use Illuminate\Http\Request;
class StudentController extends Controller
{
public function index()
{
// Eager loading untuk menghindari N+1 problem
$students = Student::with(['major', 'subjects'])->get();
return view('students.index', compact('students'));
}
public function create()
{
$majors = Major::all();
$subjects = Subject::all();
return view('students.create', compact('majors', 'subjects'));
}
public function store(Request $request)
{
$student = Student::create($request->only(['nim', 'name', 'address', 'major_id']));
// Attach mata kuliah ke mahasiswa
if ($request->has('subjects')) {
$student->subjects()->attach($request->subjects);
}
return redirect()->route('students.index')->with('success', 'Mahasiswa berhasil ditambahkan');
}
public function edit($id)
{
$student = Student::with(['subjects'])->findOrFail($id);
$majors = Major::all();
$subjects = Subject::all();
return view('students.edit', compact('student', 'majors', 'subjects'));
}
public function update(Request $request, $id)
{
$student = Student::findOrFail($id);
$student->update($request->only(['nim', 'name', 'address', 'major_id']));
// Sync mata kuliah (menghapus yang tidak ada, menambah yang baru)
if ($request->has('subjects')) {
$student->subjects()->sync($request->subjects);
}
return redirect()->route('students.index')->with('success', 'Mahasiswa berhasil diubah');
}
public function destroy($id)
{
$student = Student::findOrFail($id);
$student->delete();
return redirect()->route('students.index')->with('success', 'Mahasiswa berhasil dihapus');
}
}
9. Konfigurasi Routes
Daftarkan route resource untuk StudentController di routes/web.php:
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\StudentController;
Route::get('/', function () {
return view('welcome');
});
Route::resource('students', StudentController::class);
10. Membuat View untuk Menampilkan Data
Buat folder resources/views/students dan buat file
index.blade.php
untuk menampilkan daftar mahasiswa:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Daftar Mahasiswa</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container py-5">
<h1 class="mb-4">Daftar Mahasiswa</h1>
<a href="{{ route('students.create') }}" class="btn btn-primary mb-3">Tambah Mahasiswa</a>
<div class="table-responsive">
<table class="table table-striped table-hover">
<thead class="table-dark">
<tr>
<th>NIM</th>
<th>Nama</th>
<th>Program Studi</th>
<th>Mata Kuliah</th>
<th>Total SKS</th>
<th>Aksi</th>
</tr>
</thead>
<tbody>
@foreach($students as $student)
<tr>
<td><strong>{{ $student->nim }}</strong></td>
<td>{{ $student->name }}</td>
<td>{{ $student->major->name }}</td>
<td>
@foreach($student->subjects as $subject)
<span class="badge bg-info">{{ $subject->name }}</span>
@endforeach
</td>
<td><strong>{{ $student->subjects->sum('sks') }}</strong></td>
<td>
<a href="{{ route('students.edit', $student->id) }}" class="btn btn-sm btn-warning">Edit</a>
<form action="{{ route('students.destroy', $student->id) }}" method="POST" style="display:inline;">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-sm btn-danger" onclick="return confirm('Yakin?')">Hapus</button>
</form>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
11. Membuat View Create untuk Menambah Mahasiswa
Buat file resources/views/students/create.blade.php:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tambah Mahasiswa</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container py-5">
<div class="row justify-content-center">
<div class="col-md-8">
<h1 class="mb-4">Tambah Mahasiswa Baru</h1>
<form action="{{ route('students.store') }}" method="POST">
@csrf
<div class="mb-3">
<label class="form-label">NIM</label>
<input type="text" name="nim" class="form-control" required>
</div>
<div class="mb-3">
<label class="form-label">Nama Lengkap</label>
<input type="text" name="name" class="form-control" required>
</div>
<div class="mb-3">
<label class="form-label">Alamat</label>
<textarea name="address" class="form-control" rows="3" required></textarea>
</div>
<div class="mb-3">
<label class="form-label">Program Studi</label>
<select name="major_id" class="form-select" required>
<option value="">Pilih Program Studi</option>
@foreach($majors as $major)
<option value="{{ $major->id }}">{{ $major->name }}</option>
@endforeach
</select>
</div>
<div class="mb-3">
<label class="form-label">Mata Kuliah</label>
<div>
@foreach($subjects as $subject)
<div class="form-check">
<input type="checkbox" name="subjects[]" value="{{ $subject->id }}" class="form-check-input" id="subject_{{ $subject->id }}">
<label class="form-check-label" for="subject_{{ $subject->id }}">
{{ $subject->name }} ({{ $subject->sks }} SKS)
</label>
</div>
@endforeach
</div>
</div>
<button type="submit" class="btn btn-success">Simpan</button>
<a href="{{ route('students.index') }}" class="btn btn-secondary">Batal</a>
</form>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
12. Menjalankan dan Menguji Aplikasi
Jalankan development server Laravel:
php artisan serve
Akses aplikasi di browser melalui http://127.0.0.1:8000/students.
Anda akan melihat daftar mahasiswa dengan data program studi dan mata kuliah yang
terhubung melalui relasi database.
Uji fitur untuk menambah mahasiswa baru, edit data, dan hapus data untuk memastikan
relasi bekerja dengan baik.
13. Latihan & Tugas
Membuat halaman untuk menampilkan :
1. Semua mahasiswa beserta jurusan dan mata kuliahnya
2. Jurusan yang memiliki mahasiswa terbanyak
3. Mata kuliah yang diambil oleh mahasiswa tertentu
4. Total SKS yang diambil setiap mahasiswa
Melalui praktikum implementasi Relationship dalam Laravel, telah berhasil dipelajari dan diterapkan konsep-konsep penting dalam mengelola data relasional dengan framework modern.
hasMany(),
belongsTo(), dan belongsToMany() membuat pengelolaan
relasi menjadi jauh lebih mudah
dibandingkan menulis query SQL manual.
with() berhasil mengatasi N+1
problem dan meningkatkan
performa aplikasi secara signifikan dengan mengurangi jumlah database query.
attach() dan
sync() memberikan
cara yang elegant untuk mengelola relasi kompleks tanpa perlu manipulasi manual
tabel pivot.
Penguasaan konsep relationship di Laravel adalah fondasi penting untuk membangun aplikasi web yang lebih kompleks dengan struktur data yang terorganisir dan efisien. Dengan pemahaman ini, developer siap menghadapi tantangan dalam implementasi sistem informasi skala menengah hingga besar.