LAPORAN PRATIKUM 10

Pada pertemuan ini, kita akan membangun sebuah sistem akademik sederhana dengan beberapa relasi antar entitas, yaitu:

  • Setiap mahasiswa (Student) terhubung ke satu jurusan (Major) (relasi Many-to-One).
  • Mahasiswa dapat mengambil banyak mata kuliah (Subject) melalui tabel pivot (relasi Many-to-Many).
  • Setiap jurusan (Major) memiliki banyak mahasiswa (relasi One-to-Many).
  • Sebuah mata kuliah (Subject) dapat diikuti oleh banyak mahasiswa melalui tabel pivot (relasi Many-to-Many).

Untuk lebih jelasnya, berikut adalah Entity Relationship Diagram (ERD) dari database yang akan kita terapkan dalam proyek ini.

Pada pertemuan kali ini, kita akan memulai dengan membuat project baru karena kita akan menggunakan database yang berbeda dari sebelumnya. Untuk memudahkan, kita cukup menggunakan SQLite sebagai database-nya.

Setelah project Laravel baru berhasil dibuat secara lokal, langkah pertama yang perlu dilakukan adalah membuat migrasi database.

A. Migrasi untuk tabel majors

Untuk membuat migrasi tabel majors, jalankan perintah berikut di terminal:

php artisan make:migration create_majors_table

Kemudian tambahkan kode berikut pada function up():

Schema::create('majors', function (Blueprint $table) { 
    $table->id(); 
    $table->string('name'); 
    $table->timestamps(); 
});

B. Migration untuk tabel students

Buat migrasi database dengan perintah berikut:

bashCopyEditphp artisan make:migration create_students_table

Kemudian tambahkan kode berikut pada 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();
});

C. Migration untuk tabel subjects

Buat migrasi database dengan perintah berikut:

php artisan make:migration create_subjects_table

Kemudian tambahkan kode berikut pada function up():

Schema::create('subjects', function (Blueprint $table) { 
$table->id();
$table->string('name');
$table->integer('sks');
$table->timestamps();
});

D. Migration untuk tabel pivot student_subject

Buat migrasi database dengan perintah berikut:

bashCopyEditphp artisan make:migration create_student_subject_table

Kemudian tambahkan kode berikut pada 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 duplikasi kombinasi student_id dan subject_id
$table->unique(['student_id', 'subject_id']);
});

Setelah seluruh file migrasi selesai dibuat dan disimpan, jalankan proses migrasi dengan perintah:

php artisan migrate

jika berhasil,maka hasilnya akan seperti ini :

Langkah selanjutnya yaitu membuat model dengan relasi sesuai dengan struktur database yang telah dibuat melalui migrasi sebelumnya.

A. Model Major

Buat model dengan perintah:

php artisan make:model Major

Isi file model Major.php dengan kode berikut:

<?php 
// app/Models/Major.php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Major extends Model
{
use HasFactory;

protected $fillable = ['name'];

// Relasi: Satu jurusan memiliki banyak mahasiswa
public function students()
{
return $this->hasMany(Student::class);
}
}

B. Model Student

Buat model dengan perintah:

bashCopyEditphp artisan make:model Student

Isi file model Student.php dengan kode berikut:

<?php 
// app/Models/Student.php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Student extends Model
{
use HasFactory;

protected $fillable = ['nim', 'name', 'address', 'major_id'];

// Relasi: Mahasiswa milik satu jurusan
public function major()
{
return $this->belongsTo(Major::class);
}

// Relasi: Mahasiswa mengambil banyak mata kuliah
public function subjects()
{
return $this->belongsToMany(Subject::class);
}
}

C. Model Subject

Buat model dengan perintah:

php artisan make:model Subject

Isi file model Subject.php dengan kode berikut:

<?php 
// app/Models/Subject.php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Subject extends Model
{
use HasFactory;

protected $fillable = ['name', 'sks'];

// Relasi: Mata kuliah diambil oleh banyak mahasiswa
public function students()
{
return $this->belongsToMany(Student::class);
}
}

Langkah berikutnya adalah membuat seeder untuk mengisi data ke dalam database.

A. Seeder untuk Major

Buat seeder dengan perintah:

php artisan make:seeder MajorSeeder

Isi file MajorSeeder.php dengan kode berikut:

<?php 
// database/seeders/MajorSeeder.php

namespace Database\Seeders;

use App\Models\Major;
use Illuminate\Database\Seeder;

class MajorSeeder extends Seeder
{
public function run()
{
$majors = [
['name' => 'Teknik Informatika'],
['name' => 'Sistem Informasi'],
['name' => 'Teknik Komputer'],
['name' => 'Manajemen Informatika'],
];

foreach ($majors as $major) {
Major::create($major);
}
}
}

B. Seeder untuk Subject

Buat seeder dengan perintah:

php artisan make:seeder SubjectSeeder

Isi file SubjectSeeder.php dengan kode berikut:

<?php 
// database/seeders/SubjectSeeder.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' => 'Database', 'sks' => 3],
['name' => 'Algoritma', 'sks' => 2],
['name' => 'Jaringan Komputer', 'sks' => 3],
['name' => 'Sistem Operasi', 'sks' => 2],
];

foreach ($subjects as $subject) {
Subject::create($subject);
}
}
}

C. Seeder untuk Student

Buat seeder dengan perintah:

php artisan make:seeder StudentSeeder

Isi file StudentSeeder.php dengan kode berikut:

<?php 
// database/seeders/StudentSeeder.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' => '20210001', 'name' => 'Ahmad Rizki', 'address' => 'Jl. Merdeka No. 1', 'major_id' => 1],
['nim' => '20210002', 'name' => 'Siti Nurhaliza', 'address' => 'Jl. Sudirman No. 15', 'major_id' => 1],
['nim' => '20210003', 'name' => 'Budi Santoso', 'address' => 'Jl. Pahlawan No. 8', 'major_id' => 2],
['nim' => '20210004', 'name' => 'Dewi Kartika', 'address' => 'Jl. Diponegoro No. 22', 'major_id' => 2],
['nim' => '20210005', 'name' => 'Eko Prasetyo', 'address' => 'Jl. Gatot Subroto No. 11', 'major_id' => 3],
];

foreach ($students as $studentData) {
$student = Student::create($studentData);

// Menetapkan mata kuliah secara acak untuk setiap mahasiswa
$subjects = Subject::inRandomOrder()->take(rand(2, 4))->pluck('id');
$student->subjects()->attach($subjects);
}
}
}

D. Update DatabaseSeeder

Buka file DatabaseSeeder.php dan ubah isi method run() seperti berikut:

<?php 
// database/seeders/DatabaseSeeder.php

namespace Database\Seeders;

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
public function run()
{
$this->call([
MajorSeeder::class,
SubjectSeeder::class,
StudentSeeder::class,
]);
}
}

Setelah semua file seeder dibuat dan disimpan, jalankan perintah berikut di terminal untuk menjalankan seeder:

bashCopyEditphp artisan db:seed

Jika berhasil, maka data jurusan, mata kuliah, dan mahasiswa akan otomatis terisi ke dalam database seperti berikut

Langkah selanjutnya yaitu membuat controller untuk masing-masing model.

A. StudentController

Buat controller dengan perintah:

php artisan make:controller StudentController

Kemudian tambahkan kode berikut ke dalam file app/Http/Controllers/StudentController.php:

<?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()
{
$students = Student::with(['major', 'subjects'])->get();
return view('students.index', compact('students'));
}

public function show($id)
{
$student = Student::with(['major', 'subjects'])->findOrFail($id);
return view('students.show', compact('student'));
}

public function create()
{
$majors = Major::all();
$subjects = Subject::all();
return view('students.create', compact('majors', 'subjects'));
}

public function store(Request $request)
{
$request->validate([
'nim' => 'required|unique:students',
'name' => 'required',
'address' => 'required',
'major_id' => 'required|exists:majors,id',
'subjects' => 'required|array',
'subjects.*' => 'exists:subjects,id',
]);

$student = Student::create($request->only(['nim', 'name', 'address', 'major_id']));
$student->subjects()->attach($request->subjects);

return redirect()->route('students.index')->with('success', 'Student created successfully');
}

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);

$request->validate([
'nim' => 'required|unique:students,nim,' . $student->id,
'name' => 'required',
'address' => 'required',
'major_id' => 'required|exists:majors,id',
'subjects' => 'required|array',
'subjects.*' => 'exists:subjects,id',
]);

$student->update($request->only(['nim', 'name', 'address', 'major_id']));
$student->subjects()->sync($request->subjects);

return redirect()->route('students.index')->with('success', 'Student updated successfully');
}

public function destroy($id)
{
$student = Student::findOrFail($id);
$student->subjects()->detach();
$student->delete();

return redirect()->route('students.index')->with('success', 'Student deleted successfully');
}
}

Langkah berikutnya adalah membuat routing pada file routes/web.php:

<?php

use App\Http\Controllers\StudentController;
use Illuminate\Support\Facades\Route;

Route::get('/', function () {
return redirect()->route('students.index');
});

Route::resource('students', StudentController::class);

Kemudian buat tampilan (view) di dalam folder resources/views/students.

A. Layout Utama (resources/views/layouts/app.blade.php)

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Student Management System</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
<div class="container">
<a class="navbar-brand" href="{{ route('students.index') }}">Student Management</a>
</div>
</nav>

<div class="container mt-4">
@if(session('success'))
<div class="alert alert-success">
{{ session('success') }}
</div>
@endif

@yield('content')
</div>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

B. Tampilan Index Mahasiswa (resources/views/students/index.blade.php)

@extends('layouts.app')

@section('content')
<div class="d-flex justify-content-between align-items-center mb-4">
<h2>Daftar Mahasiswa</h2>
<a href="{{ route('students.create') }}" class="btn btn-primary">Tambah Mahasiswa</a>
</div>

<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>NIM</th>
<th>Nama</th>
<th>Jurusan</th>
<th>Mata Kuliah</th>
<th>Total SKS</th>
<th>Aksi</th>
</tr>
</thead>
<tbody>
@foreach($students as $student)
<tr>
<td>{{ $student->nim }}</td>
<td>{{ $student->name }}</td>
<td>{{ $student->major->name }}</td>
<td>
@foreach($student->subjects as $subject)
<span class="badge bg-secondary me-1">{{ $subject->name }}</span>
@endforeach
</td>
<td>{{ $student->subjects->sum('sks') }}</td>
<td>
<a href="{{ route('students.show', $student->id) }}" class="btn btn-info btn-sm">Detail</a>
<a href="{{ route('students.edit', $student->id) }}" class="btn btn-warning btn-sm">Edit</a>
<form action="{{ route('students.destroy', $student->id) }}" method="POST" class="d-inline">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-danger btn-sm" onclick="return confirm('Yakin ingin menghapus?')">Hapus</button>
</form>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@endsection

C. Tampilan Create Mahasiswa (resources/views/students/create.blade.php)

@extends('layouts.app')

@section('content')
<h2>Tambah Mahasiswa</h2>

<div class="card">
<div class="card-body">
<form action="{{ route('students.store') }}" method="POST">
@csrf

<div class="mb-3">
<label for="nim" class="form-label">NIM</label>
<input type="text" class="form-control @error('nim') is-invalid @enderror" id="nim" name="nim" value="{{ old('nim') }}">
@error('nim')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>

<div class="mb-3">
<label for="name" class="form-label">Nama</label>
<input type="text" class="form-control @error('name') is-invalid @enderror" id="name" name="name" value="{{ old('name') }}">
@error('name')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>

<div class="mb-3">
<label for="address" class="form-label">Alamat</label>
<input type="text" class="form-control @error('address') is-invalid @enderror" id="address" name="address" value="{{ old('address') }}">
@error('address')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>

<div class="mb-3">
<label for="major_id" class="form-label">Jurusan</label>
<select name="major_id" id="major_id" class="form-control @error('major_id') is-invalid @enderror">
<option value="">Pilih Jurusan</option>
@foreach ($majors as $major)
<option value="{{ $major->id }}" {{ old('major_id') == $major->id ? 'selected' : '' }}>
{{ $major->name }}
</option>
@endforeach
</select>
@error('major_id')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>

<div class="mb-3">
<label class="form-label">Mata Kuliah</label>
@error('subjects')
<div class="text-danger">{{ $message }}</div>
@enderror
@foreach ($subjects as $subject)
<div class="form-check">
<input type="checkbox" class="form-check-input" name="subjects[]" value="{{ $subject->id }}" id="subject{{ $subject->id }}" {{ in_array($subject->id, old('subjects', [])) ? 'checked' : '' }}>
<label for="subject{{ $subject->id }}" class="form-check-label">
{{ $subject->name }} ({{ $subject->sks }} SKS)
</label>
</div>
@endforeach
</div>

<button type="submit" class="btn btn-primary">Simpan</button>
<a href="{{ route('students.index') }}" class="btn btn-secondary">Kembali</a>
</form>
</div>
</div>
@endsection

Jika sudah, maka halaman akan menampilkan form input mahasiswa dan daftar data yang sudah dimasukkan seperti gambar berikut

ini indexnya :

ini create :

TUGAS

1.Query untuk menampilkan Jurusan yang memiliki mahasiswa terbanyak

Pertama, kita ubah terlebih dahulu di StudentController. Tambah kode berikut di method index():

$mostFrequentMajor = Major::withCount('students') // Count students for each major
->orderByDesc('students_count') // Order by the count descending
->first();

Query ini berfungsi untuk mencari dan mengambil satu data jurusan (Major) yang memiliki jumlah mahasiswa terbanyak. Langkah pertamanya (Major::withCount('students')) adalah mengambil semua data jurusan sambil menghitung jumlah mahasiswa yang berelasi dengan setiap jurusan. Hasil hitungan ini disimpan dalam kolom virtual bernama students_count. Kemudian (orderByDesc('students_count')) hasilnya diurutkan secara menurun berdasarkan jumlah mahasiswa tersebut. Terakhir (first()) diambil satu record pertama dari hasil pengurutan, yang secara efektif adalah jurusan dengan jumlah mahasiswa terbanyak.

Kemudian pada index (resources/views/students/index.blade.php) di bawah tabel tambahkan kode berikut:

@if ($mostFrequentMajor)
<div class="alert alert-info mt-4" role="alert">
Jurusan yang paling banyak dipilih mahasiswa adalah: <strong>{{ $mostFrequentMajor->name }}</strong> (dengan {{ $mostFrequentMajor->students_count }} mahasiswa).
</div>
@endif

Hasilnya akan menampilkan informasi tambahan di bawah tabel berupa nama jurusan dengan jumlah mahasiswa terbanyak seperti berikut

  1. Menambahkan View Detail menggunakan controller show()

Kode viewnya adalah sebagai berikut. Buat file resources/views/students/show.blade.php dan isi dengan:

@extends('layouts.app')

@section('content')
<h2>Detail Mahasiswa</h2>

<div class="card">
<div class="card-body">
<div class="mb-3">
<label for="nim" class="form-label">NIM:</label>
<p id="nim">{{ $student->nim }}</p>
</div>

<div class="mb-3">
<label for="name" class="form-label">Nama:</label>
<p id="name">{{ $student->name }}</p>
</div>

<div class="mb-3">
<label for="address" class="form-label">Alamat:</label>
<p id="address">{{ $student->address }}</p>
</div>

<div class="mb-3">
<label for="major" class="form-label">Jurusan:</label>
<p id="major">{{ $student->major->name }}</p>
</div>

<div class="mb-3">
<label class="form-label">Mata Kuliah Diambil:</label>
@if ($student->subjects->count() > 0)
<ul>
@foreach ($student->subjects as $subject)
<li>{{ $subject->name }} ({{ $subject->sks }} SKS)</li>
@endforeach
</ul>
<p><strong>Total SKS:</strong> {{ $student->subjects->sum('sks') }}</p>
@else
<p>Tidak ada mata kuliah yang diambil.</p>
@endif
</div>

<a href="{{ route('students.index') }}" class="btn btn-secondary">Kembali ke Daftar</a>
</div>
</div>
@endsection

View ini akan menampilkan informasi lengkap tentang satu mahasiswa, termasuk NIM, nama, alamat, jurusan, daftar mata kuliah yang diambil beserta jumlah SKS, serta tombol kembali ke halaman daftar mahasiswa.

  1. Menambahkan view edit dari controller update()

Buat file resources/views/students/edit.blade.php dengan kode berikut:

@extends('layouts.app')

@section('content')
<h2>Edit Mahasiswa</h2>

<div class="card">
<div class="card-body">
<form action="{{ route('students.update', $student->id) }}" method="POST">
@csrf
@method('PUT') {{-- Gunakan metode PUT untuk update --}}

<div class="mb-3">
<label for="nim" class="form-label">NIM</label>
{{-- Isi dengan data lama mahasiswa atau data inputan jika validasi gagal --}}
<input type="text" class="form-control @error('nim') is-invalid @enderror"
id="nim" name="nim" value="{{ old('nim', $student->nim) }}">
@error('nim')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>

<div class="mb-3">
<label for="name" class="form-label">Nama</label>
<input type="text" class="form-control @error('name') is-invalid @enderror"
id="name" name="name" value="{{ old('name', $student->name) }}">
@error('name')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>

<div class="mb-3">
<label for="address" class="form-label">Alamat</label>
<input type="text" class="form-control @error('address') is-invalid @enderror"
id="address" name="address" value="{{ old('address', $student->address) }}">
@error('address')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>

<div class="mb-3">
<label for="major_id" class="form-label">Jurusan</label>
<select name="major_id" id="major_id" class="form-control @error('major_id') is-invalid @enderror" >
<option value="">Pilih Jurusan</option>
@foreach ($majors as $major)
{{-- Pilih jurusan yang sudah terpilih sebelumnya --}}
<option value="{{ $major->id }}" {{ old('major_id', $student->major_id) == $major->id ? 'selected' : '' }}>
{{ $major->name }}
</option>
@endforeach
</select>
@error('major_id')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>

<div class="mb-3">
<label class="form-label">Mata Kuliah</label>
@error('subjects')
<div class="text-danger">{{ $message }}</div>
@enderror
@foreach ($subjects as $subject)
<div class="form-check">
<input type="checkbox" class="form-check-input" name="subjects[]"
value="{{ $subject->id }}" id="subject{{ $subject->id }}"
{{-- Cek apakah mata kuliah sudah dipilih --}}
{{ in_array($subject->id, old('subjects', $student->subjects->pluck('id')->toArray())) ? 'checked' : '' }}>
<label for="subject{{ $subject->id }}" class="form-check-label">
{{ $subject->name }} ({{ $subject->sks }} SKS)
</label>
</div>
@endforeach
</div>

<button type="submit" class="btn btn-primary">Update</button>
<a href="{{ route('students.index') }}" class="btn btn-secondary">Batal</a>
</form>
</div>
</div>
@endsection

Tampilan ini memungkinkan pengguna untuk mengedit data mahasiswa, mengubah jurusan, dan memilih atau menghapus mata kuliah yang diambil. Ada validasi dan feedback error pada setiap input jika ada kesalahan.

KESIMPULAN

Dalam proyek sistem akademik sederhana ini, kita telah membuat struktur database menggunakan migrasi Laravel untuk tabel majors, students, subjects, dan tabel pivot student_subject guna mengatur relasi Many-to-Many antara mahasiswa dan mata kuliah. Model Eloquent dibuat sesuai dengan relasi yang diinginkan, yaitu Major-One to Many-Student dan Student-Many to Many-Subject.

Selanjutnya, data awal dimasukkan ke database menggunakan seeder untuk tabel jurusan, mata kuliah, dan mahasiswa beserta mata kuliah yang diambil secara acak.

Controller StudentController dibuat untuk mengelola operasi CRUD mahasiswa, dengan fungsi index menampilkan daftar mahasiswa lengkap dengan jurusan dan mata kuliah, serta menampilkan jurusan dengan jumlah mahasiswa terbanyak. Fungsi show digunakan untuk menampilkan detail mahasiswa, sedangkan fungsi create dan edit menyediakan form untuk menambah dan mengubah data mahasiswa.

Route resource Laravel mengatur URL agar sesuai dengan controller, dan tampilan dibuat dengan Blade menggunakan Bootstrap untuk mendukung antarmuka yang responsif dan mudah digunakan.

Dengan demikian, aplikasi ini sudah dapat mengelola data mahasiswa, jurusan, dan mata kuliah secara lengkap, termasuk fitur menampilkan jurusan paling populer dan melakukan pengelolaan data mahasiswa secara interaktif melalui form tambah, edit, lihat detail, dan hapus data.

Leave a Comment

Your email address will not be published. Required fields are marked *