Mulai proyek dengan mengetik perintah ini di terminal
laravel new student-viewGunakan library UI dari bootstrap dengan mengetikkan perintah ini ke terminal
composer require laravel/uiPasang dependency dari laravel/ui dengan mengetik perintah ini ke terminal
npm installBangun frontend dengan menjalankan
npm run build
Buat migrasi untuk tabel majors dengan mengetikkan perintah ini ke terminal
php artisan make:migration create_majors_tableSetelah itu, buat kodenya seperti yang di bawah
<?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');
}
};
Buat migrasi untuk tabel dengan mengetikkan perintah ini ke terminal
php artisan make:migration create_students_tableSetelah itu, buat kodenya seperti yang di bawah
<?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');
}
};
Buat migrasi untuk tabel dengan mengetikkan perintah ini ke terminal
php artisan make:migration create_subjects_tableSetelah itu, buat kodenya seperti yang di bawah
<?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');
}
};
Buat migrasi untuk tabel dengan mengetikkan perintah ini ke terminal
php artisan make:migration create_student_subject_tableSetelah itu, buat kodenya seperti yang di bawah
<?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');
}
};
Setelah menyusun file migrasi, jalankan perintah ini di terminal
php artisan migrateBuat model untuk tabel majors dengan mengetikkan perintah ini ke terminal
php artisan make:model MajorSetelah itu, buat kodenya seperti yang di bawah
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
class Major extends Model
{
use HasFactory;
protected $fillable = ['name'];
// Relationship: One Major has many Students
public function students()
{
return $this->hasMany(Student::class);
}
}
Buat model untuk tabel subjects dengan mengetikkan perintah ini ke terminal
php artisan make:model StudentSetelah itu, buat kodenya seperti yang di bawah
<?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);
}
}
Buat model untuk tabel subjects dengan mengetikkan perintah ini ke terminal
php artisan make:model MajorSetelah itu, buat kodenya seperti yang di bawah
<?php
namespace App\Models;
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);
}
}
Buat seeder yang digunakan untuk mengisi tabel majors dengan mengetikkan perintah ini ke terminal
php artisan make:seeder MajorSeederSetelah itu, buat kodenya seperti yang di bawah
<?php
namespace Database\Seeders;
use App\Models\Major;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
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);
}
}
}
Buat seeder yang digunakan untuk mengisi tabel students dengan mengetikkan perintah ini ke terminal
php artisan make:seeder StudentSeederSetelah itu, buat kodenya seperti yang di bawah
<?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);
}
}
}
Buat seeder yang digunakan untuk mengisi tabel subjects dengan mengetikkan perintah ini ke terminal
php artisan make:seeder SubjectSeederSetelah itu, buat kodenya seperti yang di bawah
<?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);
}
}
}
Jalankan seeder dengan mengetikkan perintah ini di terminal
php artisan db:seedController ini digunakan untuk memanipulasi data seputar model Student dan mempresentasikannya ke view yang disimpan dalam file "students"
php artisan make:controller StudentControllerSetelah itu, buat kodenya seperti yang di bawah
<?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();
$topMajor = Major::withCount('students')
->orderBy('students_count', 'desc')
->first();
return view('students.index', compact('students', 'topMajor'));
}
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 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 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');
}
}
Controller ini digunakan untuk memanipulasi data seputar model Major dan mempresentasikannya ke view yang disimpan dalam file "majors"
php artisan make:controller MajorControllerSetelah itu, buat kodenya seperti yang di bawah
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class MajorController extends Controller
{
public function index(Request $request)
{
$sort = $request->get('sort', 'students_count');
$order = $request->get('order', 'desc');
$majors = \App\Models\Major::withCount('students')
->orderBy($sort, $order)
->get();
return view('majors.index', compact('majors', 'sort', 'order'));
}
function show($id)
{
$major = \App\Models\Major::findOrFail($id);
$students = $major->students()->with('subjects')->get();
return view('majors.show', compact('major', 'students'));
}
}
Controller ini digunakan untuk memanipulasi data seputar model Subject dan mempresentasikannya ke view yang disimpan dalam file "majors"
php artisan make:controller StudentControllerSetelah itu, buat kodenya seperti yang di bawah
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class MajorController extends Controller
{
public function index(Request $request)
{
$sort = $request->get('sort', 'students_count');
$order = $request->get('order', 'desc');
$majors = \App\Models\Major::withCount('students')
->orderBy($sort, $order)
->get();
return view('majors.index', compact('majors', 'sort', 'order'));
}
function show($id)
{
$major = \App\Models\Major::findOrFail($id);
$students = $major->students()->with('subjects')->get();
return view('majors.show', compact('major', 'students'));
}
}
Berdasarkan StudentController. Terdapat 4 view yang harus dipenuhi seperti tampilan index, tampilan show, tampilan edit, dan tampilan create.
Tempat tampilan index dari Student. Tampilan ini menjabarkan keseluruhan Student dengan NIM, Nama, Mata Kuliah, SKS. Dan juga terdapat opsi untuk melihat student secara detail, memodifikasi data Student, dan menghapus Student dari database. Kodingan untuk tampilan index Student adalah
@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>
@if ($topMajor)
<div class="alert alert-info mt-4" role="alert">
Jurusan yang memiliki mahasiswa terbanyak adalah: <strong>{{ $topMajor->name }}</strong> (dengan
{{ $topMajor->students_count }} mahasiswa).
</div>
@else
<div class="alert alert-danger mt-4" role="alert">
Mahasiswa tidak memilih jurusan apapun <a href="{{ route('students.create') }}"
class="btn btn-primary">Tambah Mahasiswa</a>
</div>
@endif
</div>
@endsection
Hasil dari tampilan index dapat dilihat pada gambar di bawah ini:
Penciptaan student dimulai dengan pengisian formulir berupa NIM, Nama, Alamat, Jurusan (Major) dan mata kuliah yang dipilih. Setelah itu, buat konfirmasi pesan bahwa penciptaan tersebut berhasil ataupun gagal.
@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
Tampilan dari halaman penciptaan Student dapat dilihat pada gambar-gambar di bawah
Digunakan untuk mengubah data seputar mahasiswa
@extends('layouts.app')
@section('content')
<h2>Tambah Mahasiswa</h2>
<div class="card">
<div class="card-body">
<form action="{{ route('students.update', ['student' => $student->id]) }}" method="POST">
@csrf
@method('PUT')
<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', $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>
<textarea class="form-control @error('address') is-invalid @enderror" id="address" name="address" rows="3">{{ old('address', $student->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', $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
@php
$studentSubjectIds = old('subjects', $student->subjects->pluck('id')->toArray());
@endphp
@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', $studentSubjectIds)) ? '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
Hasil tampilan dari kode yang telah dijabarkan adalah
Digunakan untuk menampilkan terkait mahasiwa dengan data-data yang terkait seperti data biografi, jurusan, dan mata kuliah yang diambil
@extends('layouts.app')
@section('content')
<div class="card">
<div class="card-header">
<h3>Detail Mahasiswa</h3>
</div>
<div class="card-body">
<table class="table table-bordered table-hover">
<tr>
<th>NIM</th>
<td>{{ $student->nim }}</td>
</tr>
<tr>
<th>Nama</th>
<td>{{ $student->name }}</td>
</tr>
<tr>
<th>Alamat</th>
<td>{{ $student->address }}</td>
</tr>
<tr>
<th>Jurusan</th>
<td>{{ $student->major ? $student->major->name : '-' }}</td>
</tr>
<tr>
<th>Mata Kuliah</th>
<td>
@if ($student->subjects && $student->subjects->count())
<ul class="mb-0">
@foreach ($student->subjects as $subject)
<a href="{{ route('subjects.show', $subject->id) }}"
class="btn btn-outline-dark btn-sm w-100 mb-1">
{{ $subject->name }} ({{ $subject->sks }} SKS)
</a>
@endforeach
</ul>
@else
<span>-</span>
@endif
</td>
</tr>
<tr>
<th>Jumlah SKS</th>
<td>
{{ $student->subjects->sum('sks') }}
</td>
</tr>
</table>
<a href="{{ route('students.index') }}" class="btn btn-secondary">Kembali ke Daftar</a>
</div>
</div>
@endsection
Hasil dari tampilan tersebut adalah
Dari kontroler yang terkait, hanya terdapat tampilan untuk menampilkan keseluruhan jurusan dan melihat detail dari jurusan yang terkait.
@extends('layouts.app')
@section('content')
<div class="d-flex justify-content-between align-items-center mb-4">
<h2>Daftar Jurusan</h2>
<a href="{{ route('majors.create') }}" class="btn btn-primary">Tambah Jurusan</a>
</div>
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>
Nama
<a href="{{ route('majors.index', ['sort' => 'name', 'order' => $sort === 'name' && $order === 'asc' ? 'desc' : 'asc']) }}"
class="btn btn-link btn-sm p-0">
<span>↕</span>
</a>
</th>
<th>
Jumlah Mahasiswa
<a href="{{ route('majors.index', ['sort' => 'students_count', 'order' => $sort === 'students_count' && $order === 'asc' ? 'desc' : 'asc']) }}"
class="btn btn-link btn-sm p-0">
<span>↕</span>
</a>
</th>
<th>Aksi</th>
</tr>
</thead>
<tbody>
@foreach ($majors as $major)
<tr>
<td>{{ $major->name }}</td>
<td>{{ $major->students_count }}</td>
<td>
<a href="{{ route('majors.show', $major->id) }}" class="btn btn-info btn-sm">Detail</a>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@endsection
Hasilnya adalah
Dibuat dalam bentuk tabel dengan
{{-- filepath: d:\WebDev\Laravel\student-view\resources\views\majors\show.blade.php --}}
@extends('layouts.app')
@section('content')
<div class="card">
<div class="card-header">
<h3>Detail Jurusan</h3>
</div>
<div class="card-body">
<table class="table table-bordered">
<tr>
<th>Nama Jurusan</th>
<td>{{ $major->name }}</td>
</tr>
<tr>
<th>Daftar Mahasiswa</th>
<td>
@if ($major->students && $major->students->count())
<table class="table table-sm table-bordered mb-0">
<thead>
<tr>
<th>NIM</th>
<th>Nama</th>
<th>Alamat</th>
<th>Aksi</th>
</tr>
</thead>
<tbody>
@foreach ($major->students as $student)
<tr>
<td>{{ $student->nim }}</td>
<td>{{ $student->name }}</td>
<td>{{ $student->address }}</td>
<td> <a href="{{ route('students.show', $student->id) }}"
class="btn btn-info
btn-sm">Detail</a></td>
</tr>
@endforeach
</tbody>
</table>
@else
<span>-</span>
@endif
</td>
</tr>
</table>
</div>
</div>
@endsection
Hasilnya adalah
Dari kontroler Subject, terdapat fungsi index untuk menampilkan keseluruhan mata kuliah dan terdapat fungsi untuk menampilkan detail mata kuliah yang digunakan untuk melihat info mata kuliah dan siswa-siswa yang mengambilnya.
Digunakan untuk menampilkan informasi sekilas dari subject seperti nama, SKS, dan berapa mahasiswa yang mengambilnya. Terdapat tombol untuk melihat detail dari subject
Hasilnya adalah
Menampilkan keseluruhan data dari subject dan siapa saja yang mengambilnya
Hasilnya adalah
Pada akhirnya, jalankan proyek dengan mengetikkan
php artisan serveBlog ini menghasilkan luaran sistem akademik sederhana dengan menerapkan relasi antar tabel di database menggunakan Laravel. Proyek ini memperkenalkan konsep relasi Many-to-One dan Many-to-Many melalui model Student, Major, dan Subject, serta penggunaan pivot table untuk menggambarkan hubungan many to many dari tabel Student dan Subject. Dengan pemahaman dan implementasi relasi tersebut, aplikasi menjadi lebih terstruktur dan mudah dikembangkan untuk kebutuhan akademik yang lebih kompleks di masa depan.