Laporan Praktikum

Tujuan

  • Memahami konsep relationship dalam Laravel
  • Mengimplementasikan One-to-Many dan Many-to-Many relationship
  • Membuat migration dengan foreign key
  • Menggunakan Eloquent relationship untuk query data
  • Menampilkan data dengan relationship di view

Persiapan Awal

  1. Struktur Database dan Relationship

    Dalam praktikum ini, kita akan membuat sistem akademik sederhana dengan relationship:

    • Student belongs to Major (Many-to-One)
    • Student belongs to many Subject melalui pivot table (Many-to-Many)
    • Major has many Student (One-to-Many)
    • Subject belongs to many Student melalui pivot table (Many-to-Many)
  2. ERD (Entity Relationship Diagram)

Langkah-Langkah

  1. Membuat Migration
    1. Migration untuk tabel majors

      Ketik di terminal: php artisan make:migration create_majors_table

      Kemudian buat kode berikut

      
                                // database/migrations/xxxx_xx_xx_create_majors_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('majors', function (Blueprint $table) {
                                            $table->id();
                                            $table->string('name');
                                            $table->timestamps();
                                        });
                                    }
      
                                    public function down() {
                                        Schema::dropIfExists('majors');
                                    }
                                };
                                
    2. Migration untuk tabel students

      Ketik di terminal: php artisan make:migration create_students_table

      Kemudian buat kode berikut

      
                                  // database/migrations/xxxx_xx_xx_create_students_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('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');
                                      }
                                  };
                                  
    3. Migration untuk tabel subjects

      Ketik di terminal: php artisan make:migration create_subjects_table

      Kemudian buat kode berikut

      
                                  // database/migrations/xxxx_xx_xx_create_subjects_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('subjects', function (Blueprint $table) {
                                              $table->id();
                                              $table->string('name');
                                              $table->integer('sks');
                                              $table->timestamps();
                                          });
                                      }
      
                                      public function down() {
                                          Schema::dropIfExists('subjects');
                                      }
                                  };
                                  
    4. Migration untuk pivot table student_subject

      Ketik di terminal: php artisan make:migration create_student_subject_table

      Kemudian buat kode berikut

      
                                  // database/migrations/xxxx_xx_xx_create_student_subject_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 duplikasi kombinasi student_id dan subject_id
                                              $table->unique(['student_id', 'subject_id']);
                                          });
                                      }
      
                                      public function down() {
                                          Schema::dropIfExists('student_subject');
                                      }
                                  };
                                  

    Jalakan migration dengan mengetikkan: php artisan migrate

  2. Membuat Model dengan relationship
    1. Model untuk Major

      Ketik di terminal: php artisan make:model Major

      Kemudian buat kode berikut di file app/Models/Major.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'];
      
                                      // Relationship: One Major has many Students
                                      public function students() 
                                      {
                                          return $this->hasMany(Student::class);
                                      }
                                  }
                                  
    2. Model untuk Student

      Ketik di terminal: php artisan make:model Student

      Kemudian buat kode berikut di file app/Models/Student.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'];
      
                                      // Relationship: Many Students belong to one Major
                                      public function major() 
                                      {
                                          return $this->belongsTo(Major::class);
                                      }
      
                                      // Relationship: Many Students belong to many Subjects
                                      public function subjects() 
                                      {
                                          return $this->belongsToMany(Subject::class);
                                      }
                                  }
                                  
    3. Model untuk Subject

      Ketik di terminal: php artisan make:model Subject

      Kemudian buat kode berikut di file app/Models/Subject.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'];
      
                                      // Relationship: Many Subjects belong to many Students
                                      public function students() 
                                      {
                                          return $this->belongsToMany(Student::class);
                                      }
                                  }
                                  
  3. Seeder untuk Data Sample
    1. Seeder untuk Major

      Ketik di terminal: php artisan make:seeder MajorSeeder

      Kemudian buat kode berikut di file database/seeders/MajorSeeder.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);
                                          }
                                      }
                                  }
                                  
    2. Seeder untuk Subject

      Ketik di terminal: php artisan make:seeder SubjectSeeder

      Kemudian buat kode berikut di file database/seeders/SubjectSeeder.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);
                                          }
                                      }
                                  }
                                  
    3. Seeder untuk Student

      Ketik di terminal: php artisan make:seeder StudentSeeder

      Kemudian buat kode berikut di file database/seeders/StudentSeeder.php

      
                                  // database/seeders/StudentSeeder.php
      
                                  namespace Database\Seeders;
      
                                  use App\Models\Student;
                                  use App\Models\Major;
                                  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);
      
                                              // Assign random subjects to each student
                                              $subjects = Subject::inRandomOrder()->take(rand(2, 4))->pluck('id');
                                              $student->subjects()->attach($subjects);
                                          }
                                      }
                                  }
                                  
    4. Update DatabaseSeeder
      
                                  // 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,
                                          ]);
                                      }
                                  }
                                  

    Jalankan seeder dengan mengetikkan: php artisan db:seed

  4. Membuat Controller
    1. Controller untuk Student

      Ketik di terminal: php artisan make:controller StudentController

      Kemudian buat kode berikut di file app/Http/Controllers/StudentController.php

      
                                  // app/Http/Controllers/StudentController.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 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(); // Remove all subject relationships
                                          $student->delete();
      
                                          return redirect()->route('students.index')->with('success', 'Student deleted successfully');
                                      }
                                  }
                                  
  5. Membuat routes

    Tambahkan kode berikut di file routes/web.php

    
                        // routes/web.php
    
                        use App\Http\Controllers\StudentController;
                        use Illuminate\Support\Facades\Route;
    
                        Route::get('/', function () {
                            return redirect()->route('students.index');
                        });
    
                        Route::resource('students', StudentController::class);
                        
  6. Membuat Views
    1. View untuk Layout utama

      Buat file 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>
                                  
    2. View untuk Index Students

      Buat file resources/views/students/index.blade.php

      
                                  // 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
                                  
    3. View untuk Create Student

      Buat file resources/views/students/create.blade.php

      
                                  // 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>
                                                  <textarea class="form-control @error('address') is-invalid @enderror" id="address" name="address" rows="3">{{ old('address') }}</textarea>
                                                  @error('address')
                                                      <div class="invalid-feedback">{{ $message }}</div>
                                                  @enderror
                                              </div>
      
                                              <div class="mb-3">
                                                  <label for="major_id" class="form-label">Jurusan</label>
                                                  <select class="form-control @error('major_id') is-invalid @enderror" id="major_id" name="major_id">
                                                      <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 class="form-check-input" type="checkbox" name="subjects[]" value="{{ $subject->id }}" id="subject{{ $subject->id }}"
                                                              {{ in_array($subject->id, old('subjects', [])) ? 'checked' : '' }}>
                                                          <label class="form-check-label" for="subject{{ $subject->id }}">
                                                              {{ $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