MODUL PEMROGRAMAN WEBSITE 2
Mata Kuliah: Pemrograman Website 2
Kode MK: INF2419
SKS: 3 (Praktikum)
Semester: Genap 2025/2026
Program Studi: Informatika
Fakultas: FEBI / Saintek
Universitas: UIN K.H. Abdurrahman Wahid Pekalongan
Dosen Pengampu: Mohammad Reza Maulana, M.Kom
NIP: 199110082025051002
Pertemuan: 11 dari 16
Durasi: 150 menit (3 Ã 50 menit)
Studi Kasus Berkelanjutan: Sistem Manajemen Perpustakaan
PERTEMUAN 11
CONTROLLER & VIEW (MVC PATTERN)
A. INFORMASI PERTEMUAN
| Aspek | Keterangan |
|---|---|
| Capaian Pembelajaran Lulusan (CPL) | CPL05: Memiliki pengetahuan memadai tentang cara kerja sistem komputer dan mampu merancang solusi algoritmik menggunakan framework. |
| Capaian Pembelajaran Mata Kuliah (CPMK) | CPMK05.1: Mampu merancang struktur aplikasi web backend berbasis framework dengan pendekatan MVC. |
| Sub-CPMK | Sub-CPMK05.1.3: Mampu merancang routing, controller, model, dan view sesuai kebutuhan sistem. |
| Indikator Pencapaian | Mahasiswa mampu: 1. Menjelaskan konsep dan tanggung jawab Controller dalam MVC 2. Membuat Controller untuk mengelola logika aplikasi 3. Memahami dan menggunakan routing advanced 4. Menguasai Blade templating engine 5. Passing data dari Controller ke View 6. Membuat layout master dan components 7. Menggunakan Blade directives (@foreach, @if, @extends, dll) 8. Menampilkan data database di View |
| Alokasi Waktu | âĸ Teori: 60 menit âĸ Praktikum: 90 menit âĸ Total: 150 menit (3 Ã 50 menit) |
B. PENDAHULUAN
1. Deskripsi Singkat
Pertemuan kesebelas ini membahas implementasi lengkap pola MVC (Model-View-Controller) di Laravel 12. Fokus utama adalah pada Controller sebagai penghubung antara Model dan View, serta Blade templating engine untuk membuat tampilan yang dinamis dan reusable. Mahasiswa akan belajar bagaimana data dari database (Model) diproses oleh Controller dan ditampilkan ke user melalui View dengan Blade template.
2. Keterkaitan dengan Pertemuan Lain
Pertemuan ini merupakan penyatuan konsep-konsep yang telah dipelajari:
- Pertemuan 9: Konsep MVC telah dijelaskan secara teori
- Pertemuan 10: Model & Migration sudah dibuat, data sudah siap
- Pertemuan 11: [SEKARANG] Implementasi Controller & View untuk menampilkan data
- Pertemuan 12-13: CRUD lengkap menggunakan MVC pattern
- Pertemuan 14-15: Authentication dan transaksi dengan MVC
Alur Pembelajaran MVC:
Pertemuan 9 â Pengenalan MVC (Konsep)
Pertemuan 10 â Model (Database Layer)
Pertemuan 11 â Controller & View (Logic & Presentation Layer)
Pertemuan 12 â CRUD Buku (Implementasi Lengkap MVC)3. Manfaat Pembelajaran
- Memahami separation of concerns dalam aplikasi web
- Mampu membangun aplikasi dengan arsitektur yang terstruktur
- Dapat membuat tampilan yang reusable dengan Blade components
- Menguasai cara passing data dari backend ke frontend
- Siap mengimplementasikan CRUD operations
4. Relevansi dengan Studi Kasus
Dalam sistem perpustakaan, Controller & View digunakan untuk:
- BukuController: Menangani logika tampilan daftar buku, detail buku
- AnggotaController: Mengelola tampilan data anggota
- Blade Layout: Template konsisten untuk semua halaman
- Components: Navbar, sidebar, footer yang reusable
- Directives: Loop untuk menampilkan multiple data, conditional untuk status
C. MATERI TEORI
1. Review: MVC Pattern
a. Apa itu MVC?
MVC (Model-View-Controller) adalah design pattern untuk memisahkan aplikasi menjadi 3 komponen utama:
âââââââââââââââââââââââââââââââââââââââââââââââââââ
â MVC ARCHITECTURE â
âââââââââââââââââââââââââââââââââââââââââââââââââââ¤
â â
â ââââââââââââ ââââââââââââ âââââââââââ
â â MODEL âââââââēâCONTROLLERâââââââēâ VIEW ââ
â ââââââââââââ ââââââââââââ âââââââââââ
â ⲠⲠâ â
â â â â â
â ââââââââââ ââââââââââ âââââââââââ
â âDatabaseâ â Logic â â HTML ââ
â â Data â âBusinessâ â CSS ââ
â ââââââââââ ââââââââââ âââââââââââ
â â
âââââââââââââââââââââââââââââââââââââââââââââââââââKomponen MVC:
| Komponen | Tanggung Jawab | File Laravel |
|---|---|---|
| Model | Interaksi dengan database, business rules | app/Models/Buku.php |
| View | Tampilan UI, presentasi data | resources/views/buku/index.blade.php |
| Controller | Logika aplikasi, penghubung Model-View | app/Http/Controllers/BukuController.php |
b. Alur Kerja MVC di Laravel
User Request
â
Route (web.php)
â
Controller
â
Model (Query Database)
â
Controller (Process Data)
â
View (Blade Template)
â
Response HTML ke UserContoh Konkret:
// 1. Route
Route::get('/buku', [BukuController::class, 'index']);
// 2. Controller
public function index() {
$bukus = Buku::all(); // Model
return view('buku.index', [ // View
'bukus' => $bukus
]);
}
// 3. Model (sudah dibuat di Pertemuan 10)
class Buku extends Model { ... }
// 4. View (Blade)
@foreach($bukus as $buku)
<h3>{{ $buku->judul }}</h3>
@endforeachc. Mengapa MVC Penting?
Tanpa MVC (Spaghetti Code):
// Semua logic campur aduk dalam satu file
<?php
$conn = mysqli_connect(...);
$query = "SELECT * FROM buku";
$result = mysqli_query($conn, $query);
?>
<html>
<?php while($row = mysqli_fetch_assoc($result)): ?>
<h3><?php echo $row['judul']; ?></h3>
<?php endwhile; ?>
</html>
<?php mysqli_close($conn); ?>Dengan MVC (Clean & Organized):
// Controller
public function index() {
$bukus = Buku::all();
return view('buku.index', compact('bukus'));
}
// View
@foreach($bukus as $buku)
<h3>{{ $buku->judul }}</h3>
@endforeachKeuntungan MVC:
- â Separation of Concerns: Setiap komponen punya tugas jelas
- â Maintainability: Mudah maintenance dan update
- â Reusability: Component bisa dipakai ulang
- â Testability: Mudah untuk unit testing
- â Team Work: Developer bisa kerja parallel
- â Scalability: Mudah dikembangkan
2. Controller di Laravel
a. Apa itu Controller?
Controller adalah class yang menangani logika aplikasi. Controller menerima request, memproses data, dan mengembalikan response.
Tanggung Jawab Controller:
- Menerima input dari user (request)
- Validasi input
- Berinteraksi dengan Model (database)
- Memproses business logic
- Mengirim data ke View
- Mengembalikan response
Lokasi File: app/Http/Controllers/
b. Struktur Controller
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Buku;
class BukuController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
$bukus = Buku::all();
return view('buku.index', compact('bukus'));
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
$buku = Buku::findOrFail($id);
return view('buku.show', compact('buku'));
}
}Penjelasan:
namespace App\Http\Controllers: Namespace controlleruse App\Models\Buku: Import Model Bukuextends Controller: Inherit dari base Controllerpublic function index(): Method untuk list datapublic function show($id): Method untuk detail datacompact('bukus'): Shorthand untuk passing variable ke view
c. Jenis-jenis Controller
1. Basic Controller:
class BukuController extends Controller
{
public function index() { ... }
public function show($id) { ... }
}2. Resource Controller:
// Otomatis punya 7 methods:
// index, create, store, show, edit, update, destroy
php artisan make:controller BukuController --resource3. Single Action Controller:
class ShowBukuController extends Controller
{
public function __invoke($id)
{
return view('buku.show');
}
}4. API Resource Controller:
// Tanpa create dan edit (untuk API)
php artisan make:controller BukuController --apid. Passing Data ke View
Laravel menyediakan beberapa cara untuk passing data:
1. Array Associative:
return view('buku.index', [
'bukus' => $bukus,
'title' => 'Daftar Buku'
]);2. Compact Function:
$bukus = Buku::all();
$title = 'Daftar Buku';
return view('buku.index', compact('bukus', 'title'));3. With Method:
return view('buku.index')
->with('bukus', $bukus)
->with('title', 'Daftar Buku');4. With Array:
return view('buku.index')->with([
'bukus' => $bukus,
'title' => 'Daftar Buku'
]);Best Practice: Gunakan compact() karena paling readable.
3. Routing Advanced
a. Review Basic Routing
// Basic GET route
Route::get('/buku', function () {
return view('buku.index');
});
// Route dengan parameter
Route::get('/buku/{id}', function ($id) {
return "Buku ID: $id";
});b. Controller Routing
Method Syntax:
Route::get('/buku', [BukuController::class, 'index']);
Route::get('/buku/{id}', [BukuController::class, 'show']);c. Resource Routing
Resource routing membuat semua route CRUD otomatis:
Route::resource('buku', BukuController::class);Ini sama dengan:
Route::get('/buku', [BukuController::class, 'index'])->name('buku.index');
Route::get('/buku/create', [BukuController::class, 'create'])->name('buku.create');
Route::post('/buku', [BukuController::class, 'store'])->name('buku.store');
Route::get('/buku/{buku}', [BukuController::class, 'show'])->name('buku.show');
Route::get('/buku/{buku}/edit', [BukuController::class, 'edit'])->name('buku.edit');
Route::put('/buku/{buku}', [BukuController::class, 'update'])->name('buku.update');
Route::delete('/buku/{buku}', [BukuController::class, 'destroy'])->name('buku.destroy');Tabel Resource Routes:
| HTTP Method | URI | Action | Route Name |
|---|---|---|---|
| GET | /buku | index | buku.index |
| GET | /buku/create | create | buku.create |
| POST | /buku | store | buku.store |
| GET | /buku/{id} | show | buku.show |
| GET | /buku/{id}/edit | edit | buku.edit |
| PUT/PATCH | /buku/{id} | update | buku.update |
| DELETE | /buku/{id} | destroy | buku.destroy |
d. Route Naming
Named routes memudahkan generate URL:
// Define named route
Route::get('/buku', [BukuController::class, 'index'])->name('buku.index');
// Generate URL di Blade
<a href="{{ route('buku.index') }}">Daftar Buku</a>
// Redirect di Controller
return redirect()->route('buku.index');e. Route Groups
Group by Prefix:
Route::prefix('admin')->group(function () {
Route::get('/buku', [BukuController::class, 'index']);
Route::get('/anggota', [AnggotaController::class, 'index']);
});
// URL: /admin/buku, /admin/anggotaGroup by Middleware:
Route::middleware(['auth'])->group(function () {
Route::resource('buku', BukuController::class);
Route::resource('anggota', AnggotaController::class);
});Group by Name:
Route::name('admin.')->group(function () {
Route::get('/buku', [BukuController::class, 'index'])->name('buku.index');
// Route name: admin.buku.index
});f. Route Parameters
Required Parameters:
Route::get('/buku/{id}', [BukuController::class, 'show']);
// Controller
public function show($id) {
$buku = Buku::findOrFail($id);
return view('buku.show', compact('buku'));
}Optional Parameters:
Route::get('/buku/{kategori?}', [BukuController::class, 'filter']);
// Controller
public function filter($kategori = null) {
$query = Buku::query();
if ($kategori) {
$query->where('kategori', $kategori);
}
$bukus = $query->get();
return view('buku.index', compact('bukus'));
}Regular Expression Constraints:
// Hanya terima numeric
Route::get('/buku/{id}', [BukuController::class, 'show'])
->where('id', '[0-9]+');
// Multiple constraints
Route::get('/buku/{kategori}/{tahun}', [BukuController::class, 'filter'])
->where(['kategori' => '[A-Za-z]+', 'tahun' => '[0-9]{4}']);g. Route Model Binding
Laravel otomatis inject Model berdasarkan ID:
// Automatic binding (by ID)
Route::get('/buku/{buku}', [BukuController::class, 'show']);
public function show(Buku $buku) {
// Laravel otomatis find Buku by ID
// Tidak perlu: $buku = Buku::findOrFail($id);
return view('buku.show', compact('buku'));
}
// Custom binding (by field lain)
Route::get('/buku/{buku:kode_buku}', [BukuController::class, 'show']);4. Blade Templating Engine
a. Apa itu Blade?
Blade adalah templating engine bawaan Laravel yang powerful dan mudah digunakan.
Keuntungan Blade:
- â Syntax sederhana dan intuitif
- â Template inheritance (layouts)
- â Components & slots
- â Directives untuk control structures
- â Raw PHP tetap bisa digunakan
- â Template caching otomatis
- â XSS protection built-in
Lokasi: resources/views/
Extension: .blade.php
b. Blade Syntax Basics
Menampilkan Data:
{{-- Escaped (safe dari XSS) --}}
<h1>{{ $title }}</h1>
<p>{{ $buku->judul }}</p>
{{-- Unescaped (raw HTML) --}}
<div>{!! $content !!}</div>
{{-- Dengan default value --}}
<p>{{ $description ?? 'Tidak ada deskripsi' }}</p>Comments:
{{-- Ini komentar Blade (tidak muncul di HTML) --}}
<!-- Ini komentar HTML (muncul di source) -->Displaying Raw Text:
@verbatim
<div>{{ $variable }}</div>
@endverbatim
{{-- Output: <div>{{ $variable }}</div> --}}c. Blade Directives
1. Conditional Directives:
{{-- @if, @elseif, @else --}}
@if ($buku->stok > 0)
<span class="badge bg-success">Tersedia</span>
@elseif ($buku->stok == 0)
<span class="badge bg-danger">Habis</span>
@else
<span class="badge bg-warning">Stok Tidak Valid</span>
@endif
{{-- @unless (kebalikan if) --}}
@unless ($buku->stok == 0)
<button>Pinjam</button>
@endunless
{{-- @isset, @empty --}}
@isset($buku->isbn)
<p>ISBN: {{ $buku->isbn }}</p>
@endisset
@empty($buku->deskripsi)
<p>Tidak ada deskripsi</p>
@endempty
{{-- @auth, @guest --}}
@auth
<a href="/logout">Logout</a>
@endauth
@guest
<a href="/login">Login</a>
@endguest2. Loop Directives:
{{-- @foreach --}}
@foreach ($bukus as $buku)
<div class="card">
<h3>{{ $buku->judul }}</h3>
<p>{{ $buku->pengarang }}</p>
</div>
@endforeach
{{-- @forelse (foreach dengan else) --}}
@forelse ($bukus as $buku)
<div>{{ $buku->judul }}</div>
@empty
<p>Tidak ada data buku</p>
@endforelse
{{-- @for --}}
@for ($i = 0; $i < 10; $i++)
<p>Nomor: {{ $i }}</p>
@endfor
{{-- @while --}}
@while (true)
<p>Loop</p>
@break
@endwhile
{{-- @continue, @break --}}
@foreach ($bukus as $buku)
@if ($buku->stok == 0)
@continue
@endif
<div>{{ $buku->judul }}</div>
@if ($loop->index >= 10)
@break
@endif
@endforeach3. Loop Variable ($loop):
@foreach ($bukus as $buku)
@if ($loop->first)
<div>Buku Pertama</div>
@endif
<div class="{{ $loop->even ? 'bg-gray' : 'bg-white' }}">
{{ $loop->iteration }}. {{ $buku->judul }}
</div>
@if ($loop->last)
<div>Buku Terakhir</div>
@endif
@endforeach$loop Properties:
$loop->index: Index (mulai dari 0)$loop->iteration: Iteration (mulai dari 1)$loop->remaining: Sisa iteration$loop->count: Total items$loop->first: Boolean, item pertama?$loop->last: Boolean, item terakhir?$loop->even: Boolean, index genap?$loop->odd: Boolean, index ganjil?$loop->depth: Nesting level$loop->parent: Parent loop variable
d. Template Inheritance
Master Layout:
File: resources/views/layouts/app.blade.php
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@yield('title') - Perpustakaan</title>
{{-- CSS --}}
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
@stack('styles')
</head>
<body>
{{-- Navbar --}}
@include('layouts.navbar')
{{-- Main Content --}}
<main class="container mt-4">
@yield('content')
</main>
{{-- Footer --}}
@include('layouts.footer')
{{-- JavaScript --}}
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
@stack('scripts')
</body>
</html>Child View:
File: resources/views/buku/index.blade.php
@extends('layouts.app')
@section('title', 'Daftar Buku')
@push('styles')
<style>
.card-custom { border: 2px solid #007bff; }
</style>
@endpush
@section('content')
<h1>Daftar Buku</h1>
<div class="row">
@foreach ($bukus as $buku)
<div class="col-md-4">
<div class="card">
<div class="card-body">
<h5>{{ $buku->judul }}</h5>
<p>{{ $buku->pengarang }}</p>
</div>
</div>
</div>
@endforeach
</div>
@endsection
@push('scripts')
<script>
console.log('Buku page loaded');
</script>
@endpushDirectives:
@extends('layouts.app'): Inherit dari layout@section('content'): Define section content@yield('content'): Placeholder untuk section@include('layouts.navbar'): Include partial view@push('scripts'): Push ke stack@stack('scripts'): Output stack
e. Components
Creating Component:
php artisan make:component AlertFile: app/View/Components/Alert.php
<?php
namespace App\View\Components;
use Illuminate\View\Component;
class Alert extends Component
{
public $type;
public $message;
public function __construct($type = 'info', $message = '')
{
$this->type = $type;
$this->message = $message;
}
public function render()
{
return view('components.alert');
}
}File: resources/views/components/alert.blade.php
<div class="alert alert-{{ $type }} alert-dismissible fade show" role="alert">
{{ $message }}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>Usage:
<x-alert type="success" message="Data berhasil disimpan!" />
<x-alert type="danger" message="Terjadi kesalahan!" />5. Best Practices MVC Laravel
a. Controller Best Practices
â DO:
// 1. Skinny Controller - Logic di Model atau Service
public function index()
{
$bukus = Buku::aktif()->latest()->get();
return view('buku.index', compact('bukus'));
}
// 2. Single Responsibility
public function destroy($id)
{
$buku = Buku::findOrFail($id);
$buku->delete();
return redirect()->route('buku.index')
->with('success', 'Buku berhasil dihapus');
}
// 3. Validasi di Form Request (akan dipelajari pertemuan 12)
public function store(StoreBukuRequest $request)
{
Buku::create($request->validated());
return redirect()->route('buku.index');
}â DON'T:
// 1. Fat Controller - terlalu banyak logic
public function index()
{
$bukus = DB::table('buku')
->select('*')
->where('stok', '>', 0)
->orderBy('created_at', 'desc')
->get();
$formatted = [];
foreach ($bukus as $buku) {
$formatted[] = [
'judul' => $buku->judul,
'harga_format' => 'Rp ' . number_format($buku->harga),
// ... banyak processing
];
}
return view('buku.index', ['bukus' => $formatted]);
}
// 2. Query di View
return view('buku.index'); // View langsung query Buku::all()b. View Best Practices
â DO:
{{-- 1. Gunakan layout inheritance --}}
@extends('layouts.app')
{{-- 2. Extract reusable components --}}
@include('partials.buku-card', ['buku' => $buku])
{{-- 3. Use Blade directives --}}
@forelse ($bukus as $buku)
<div>{{ $buku->judul }}</div>
@empty
<p>Tidak ada data</p>
@endforelseâ DON'T:
{{-- 1. Jangan query di view --}}
@php
$bukus = \App\Models\Buku::all();
@endphp
{{-- 2. Jangan business logic di view --}}
@php
$total = 0;
foreach ($bukus as $buku) {
$total += $buku->harga * $buku->stok;
}
@endphpc. Routing Best Practices
â DO:
// 1. Gunakan resource routes
Route::resource('buku', BukuController::class);
// 2. Route grouping
Route::middleware(['auth'])->group(function () {
Route::resource('buku', BukuController::class);
Route::resource('anggota', AnggotaController::class);
});
// 3. Named routes
Route::get('/buku', [BukuController::class, 'index'])->name('buku.index');â DON'T:
// 1. Closure yang kompleks di route
Route::get('/buku', function () {
// Puluhan baris code
$bukus = Buku::where(...)
->with(...)
->orderBy(...)
->paginate(10);
return view('buku.index', compact('bukus'));
});D. PRAKTIKUM
1. Tujuan Praktikum
- Membuat Controller untuk mengelola data buku
- Setup routing untuk buku
- Membuat layout master dengan Blade
- Membuat view untuk menampilkan list buku
- Membuat view untuk detail buku
- Menggunakan Blade directives
- Passing data dari Controller ke View
2. PRAKTIKUM 1: Membuat Blade Layout Master
Tujuan
Membuat template master yang akan digunakan semua halaman.
Langkah-langkah
a. Buat Folder Structure
cd resources/views
mkdir layouts
mkdir partials
mkdir buku
mkdir anggotab. Buat Layout Master
File: resources/views/layouts/app.blade.php
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>@yield('title', 'Perpustakaan') - Sistem Perpustakaan</title>
{{-- Bootstrap CSS --}}
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
{{-- Bootstrap Icons --}}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css">
{{-- Custom CSS --}}
<style>
body {
min-height: 100vh;
display: flex;
flex-direction: column;
}
main {
flex: 1;
}
.navbar-brand {
font-weight: bold;
font-size: 1.3rem;
}
footer {
margin-top: auto;
background-color: #f8f9fa;
padding: 2rem 0;
}
</style>
@stack('styles')
</head>
<body>
{{-- Navbar --}}
@include('layouts.navbar')
{{-- Main Content --}}
<main class="py-4">
<div class="container">
{{-- Alert Messages --}}
@if (session('success'))
<div class="alert alert-success alert-dismissible fade show" role="alert">
<i class="bi bi-check-circle-fill"></i>
{{ session('success') }}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
@endif
@if (session('error'))
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<i class="bi bi-exclamation-triangle-fill"></i>
{{ session('error') }}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
@endif
@if (session('info'))
<div class="alert alert-info alert-dismissible fade show" role="alert">
<i class="bi bi-info-circle-fill"></i>
{{ session('info') }}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
@endif
{{-- Page Content --}}
@yield('content')
</div>
</main>
{{-- Footer --}}
@include('layouts.footer')
{{-- Bootstrap JS --}}
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
@stack('scripts')
</body>
</html>c. Buat Navbar Component
File: resources/views/layouts/navbar.blade.php
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
<div class="container">
<a class="navbar-brand" href="{{ url('/') }}">
<i class="bi bi-book-fill"></i>
Perpustakaan
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<a class="nav-link {{ Request::is('/') ? 'active' : '' }}" href="{{ url('/') }}">
<i class="bi bi-house-door"></i> Home
</a>
</li>
<li class="nav-item">
<a class="nav-link {{ Request::is('buku*') ? 'active' : '' }}" href="{{ route('buku.index') }}">
<i class="bi bi-book"></i> Buku
</a>
</li>
<li class="nav-item">
<a class="nav-link {{ Request::is('anggota*') ? 'active' : '' }}" href="{{ route('anggota.index') }}">
<i class="bi bi-people"></i> Anggota
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">
<i class="bi bi-arrow-left-right"></i> Transaksi
</a>
</li>
</ul>
</div>
</div>
</nav>d. Buat Footer Component
File: resources/views/layouts/footer.blade.php
<footer class="bg-light border-top">
<div class="container">
<div class="row py-4">
<div class="col-md-6">
<h5><i class="bi bi-book-fill text-primary"></i> Sistem Perpustakaan</h5>
<p class="text-muted mb-0">
Sistem Manajemen Perpustakaan menggunakan Laravel 12
</p>
</div>
<div class="col-md-3">
<h6>Menu</h6>
<ul class="list-unstyled">
<li><a href="{{ url('/') }}" class="text-decoration-none">Home</a></li>
<li><a href="{{ route('buku.index') }}" class="text-decoration-none">Buku</a></li>
<li><a href="{{ route('anggota.index') }}" class="text-decoration-none">Anggota</a></li>
</ul>
</div>
<div class="col-md-3">
<h6>Kontak</h6>
<p class="text-muted small mb-0">
<i class="bi bi-envelope"></i> perpustakaan@example.com<br />
<i class="bi bi-telephone"></i> (021) 1234-5678
</p>
</div>
</div>
<div class="row border-top pt-3">
<div class="col text-center text-muted small">
<p class="mb-0">
© {{ date('Y') }} Sistem Perpustakaan.
Built with <i class="bi bi-heart-fill text-danger"></i> using Laravel 12.
</p>
</div>
</div>
</div>
</footer>e. Test Layout - Buat Home Page
File: resources/views/home.blade.php
@extends('layouts.app')
@section('title', 'Home')
@section('content')
<div class="text-center py-5">
<h1 class="display-4">
<i class="bi bi-book-fill text-primary"></i>
Selamat Datang di Sistem Perpustakaan
</h1>
<p class="lead text-muted">
Sistem manajemen perpustakaan modern menggunakan Laravel 12
</p>
<div class="row mt-5">
<div class="col-md-4">
<div class="card border-primary">
<div class="card-body text-center">
<i class="bi bi-book display-1 text-primary"></i>
<h5 class="card-title mt-3">Kelola Buku</h5>
<p class="card-text">Manajemen koleksi buku perpustakaan</p>
<a href="{{ route('buku.index') }}" class="btn btn-primary">
Lihat Buku <i class="bi bi-arrow-right"></i>
</a>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card border-success">
<div class="card-body text-center">
<i class="bi bi-people display-1 text-success"></i>
<h5 class="card-title mt-3">Kelola Anggota</h5>
<p class="card-text">Manajemen data anggota perpustakaan</p>
<a href="{{ route('anggota.index') }}" class="btn btn-success">
Lihat Anggota <i class="bi bi-arrow-right"></i>
</a>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card border-info">
<div class="card-body text-center">
<i class="bi bi-arrow-left-right display-1 text-info"></i>
<h5 class="card-title mt-3">Transaksi</h5>
<p class="card-text">Peminjaman dan pengembalian buku</p>
<a href="#" class="btn btn-info text-white">
Transaksi <i class="bi bi-arrow-right"></i>
</a>
</div>
</div>
</div>
</div>
</div>
@endsectionf. Setup Route Home
Edit routes/web.php:
<?php
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
return view('home');
})->name('home');g. Testing
- Jalankan server:
php artisan serve - Akses:
http://localhost:8000 - Verifikasi:
- Navbar muncul dengan benar
- Footer muncul di bawah
- Card untuk Buku, Anggota, Transaksi ada
- Layout responsive (test di mobile view)
3. PRAKTIKUM 2: Membuat BukuController
Tujuan
Membuat controller untuk mengelola tampilan data buku.
Langkah-langkah
a. Generate Controller
php artisan make:controller BukuController --resourceOutput:
Controller created successfully.File ter-generate di: app/Http/Controllers/BukuController.php
b. Edit BukuController
File: app/Http/Controllers/BukuController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Buku;
class BukuController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
// Ambil semua data buku dari database
$bukus = Buku::latest()->get();
// Statistik untuk card
$totalBuku = Buku::count();
$bukuTersedia = Buku::where('stok', '>', 0)->count();
$bukuHabis = Buku::where('stok', 0)->count();
// Return view dengan data
return view('buku.index', compact(
'bukus',
'totalBuku',
'bukuTersedia',
'bukuHabis'
));
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
// Akan diimplementasi di pertemuan 12
return view('buku.create');
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
// Akan diimplementasi di pertemuan 12
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
// Find buku by ID, throw 404 if not found
$buku = Buku::findOrFail($id);
// Return view detail buku
return view('buku.show', compact('buku'));
}
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id)
{
// Akan diimplementasi di pertemuan 12
$buku = Buku::findOrFail($id);
return view('buku.edit', compact('buku'));
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
// Akan diimplementasi di pertemuan 12
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
// Akan diimplementasi di pertemuan 12
}
/**
* Filter buku berdasarkan kategori.
*/
public function filterKategori($kategori)
{
$bukus = Buku::where('kategori', $kategori)->latest()->get();
$totalBuku = $bukus->count();
$bukuTersedia = $bukus->where('stok', '>', 0)->count();
$bukuHabis = $bukus->where('stok', 0)->count();
return view('buku.index', compact(
'bukus',
'totalBuku',
'bukuTersedia',
'bukuHabis',
'kategori'
));
}
}c. Setup Routes
Edit routes/web.php:
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\BukuController;
use App\Http\Controllers\AnggotaController;
Route::get('/', function () {
return view('home');
})->name('home');
// Resource route untuk Buku
Route::resource('buku', BukuController::class);
// Custom route untuk filter kategori
Route::get('/buku/kategori/{kategori}', [BukuController::class, 'filterKategori'])
->name('buku.kategori');
// Resource route untuk Anggota (akan dibuat nanti)
Route::resource('anggota', AnggotaController::class);d. Test Routes
php artisan route:list --name=bukuOutput:
GET|HEAD buku ................ buku.index âē BukuController@index
GET|HEAD buku/create ......... buku.create âē BukuController@create
POST buku ................ buku.store âē BukuController@store
GET|HEAD buku/{buku} ......... buku.show âē BukuController@show
GET|HEAD buku/{buku}/edit .... buku.edit âē BukuController@edit
PUT|PATCH buku/{buku} ......... buku.update âē BukuController@update
DELETE buku/{buku} ......... buku.destroy âē BukuController@destroy
GET|HEAD buku/kategori/{kategori} buku.kategori âē BukuController@filterKategori4. PRAKTIKUM 3: View Daftar Buku (Index)
Tujuan
Membuat halaman untuk menampilkan daftar semua buku.
Langkah-langkah
a. Buat View Index
File: resources/views/buku/index.blade.php
@extends('layouts.app')
@section('title', 'Daftar Buku')
@section('content')
<div class="d-flex justify-content-between align-items-center mb-4">
<h1>
<i class="bi bi-book"></i>
Daftar Buku
</h1>
<a href="{{ route('buku.create') }}" class="btn btn-primary">
<i class="bi bi-plus-circle"></i> Tambah Buku
</a>
</div>
{{-- Statistik Cards --}}
<div class="row mb-4">
<div class="col-md-4">
<div class="card border-primary">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="text-muted mb-1">Total Buku</h6>
<h2 class="mb-0">{{ $totalBuku }}</h2>
</div>
<div class="text-primary">
<i class="bi bi-book-fill" style="font-size: 3rem;"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card border-success">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="text-muted mb-1">Buku Tersedia</h6>
<h2 class="mb-0">{{ $bukuTersedia }}</h2>
</div>
<div class="text-success">
<i class="bi bi-check-circle-fill" style="font-size: 3rem;"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card border-danger">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="text-muted mb-1">Buku Habis</h6>
<h2 class="mb-0">{{ $bukuHabis }}</h2>
</div>
<div class="text-danger">
<i class="bi bi-x-circle-fill" style="font-size: 3rem;"></i>
</div>
</div>
</div>
</div>
</div>
</div>
{{-- Filter Kategori --}}
<div class="card mb-4">
<div class="card-body">
<h6 class="card-title">
<i class="bi bi-funnel"></i> Filter Kategori:
</h6>
<div class="btn-group" role="group">
<a href="{{ route('buku.index') }}" class="btn btn-sm {{ !isset($kategori) ? 'btn-primary' : 'btn-outline-primary' }}">
Semua
</a>
<a href="{{ route('buku.kategori', 'Programming') }}" class="btn btn-sm {{ isset($kategori) && $kategori == 'Programming' ? 'btn-primary' : 'btn-outline-primary' }}">
Programming
</a>
<a href="{{ route('buku.kategori', 'Database') }}" class="btn btn-sm {{ isset($kategori) && $kategori == 'Database' ? 'btn-primary' : 'btn-outline-primary' }}">
Database
</a>
<a href="{{ route('buku.kategori', 'Web Design') }}" class="btn btn-sm {{ isset($kategori) && $kategori == 'Web Design' ? 'btn-primary' : 'btn-outline-primary' }}">
Web Design
</a>
<a href="{{ route('buku.kategori', 'Networking') }}" class="btn btn-sm {{ isset($kategori) && $kategori == 'Networking' ? 'btn-primary' : 'btn-outline-primary' }}">
Networking
</a>
<a href="{{ route('buku.kategori', 'Data Science') }}" class="btn btn-sm {{ isset($kategori) && $kategori == 'Data Science' ? 'btn-primary' : 'btn-outline-primary' }}">
Data Science
</a>
</div>
</div>
</div>
{{-- Daftar Buku --}}
@forelse ($bukus as $buku)
<div class="card mb-3">
<div class="card-body">
<div class="row">
<div class="col-md-2 text-center">
<i class="bi bi-book text-primary" style="font-size: 4rem;"></i>
<div class="mt-2">
<span class="badge bg-{{ $buku->kategori == 'Programming' ? 'primary' : ($buku->kategori == 'Database' ? 'success' : ($buku->kategori == 'Web Design' ? 'info' : ($buku->kategori == 'Networking' ? 'warning' : 'danger'))) }}">
{{ $buku->kategori }}
</span>
</div>
</div>
<div class="col-md-7">
<h5 class="card-title">
<a href="{{ route('buku.show', $buku->id) }}" class="text-decoration-none">
{{ $buku->judul }}
</a>
</h5>
<p class="card-text text-muted mb-2">
<i class="bi bi-person"></i> {{ $buku->pengarang }} |
<i class="bi bi-building"></i> {{ $buku->penerbit }} |
<i class="bi bi-calendar"></i> {{ $buku->tahun_terbit }}
</p>
@if ($buku->isbn)
<p class="card-text small text-muted mb-1">
<i class="bi bi-upc"></i> ISBN: {{ $buku->isbn }}
</p>
@endif
@if ($buku->deskripsi)
<p class="card-text">
{{ Str::limit($buku->deskripsi, 150) }}
</p>
@endif
</div>
<div class="col-md-3 text-end">
<h4 class="text-primary mb-2">
{{ $buku->harga_format }}
</h4>
<div class="mb-3">
@if ($buku->stok > 0)
<span class="badge bg-success">
<i class="bi bi-check-circle"></i> Tersedia
</span>
<div class="text-muted small mt-1">
Stok: {{ $buku->stok }} buku
</div>
@else
<span class="badge bg-danger">
<i class="bi bi-x-circle"></i> Habis
</span>
@endif
</div>
<div class="btn-group-vertical d-grid gap-2">
<a href="{{ route('buku.show', $buku->id) }}" class="btn btn-sm btn-info text-white">
<i class="bi bi-eye"></i> Detail
</a>
<a href="{{ route('buku.edit', $buku->id) }}" class="btn btn-sm btn-warning">
<i class="bi bi-pencil"></i> Edit
</a>
</div>
</div>
</div>
</div>
</div>
@empty
<div class="alert alert-info">
<i class="bi bi-info-circle"></i>
Tidak ada data buku
@isset($kategori)
dengan kategori <strong>{{ $kategori }}</strong>
@endisset
</div>
@endforelse
@if ($bukus->count() > 0)
<div class="text-center mt-4">
<p class="text-muted">
Menampilkan {{ $bukus->count() }} buku
@isset($kategori)
dari kategori <strong>{{ $kategori }}</strong>
@endisset
</p>
</div>
@endif
@endsectionb. Test View
- Akses:
http://localhost:8000/buku - Verifikasi:
- Card statistik muncul
- Filter kategori berfungsi
- Daftar buku tampil dengan card
- Badge kategori dengan warna berbeda
- Status stok (tersedia/habis) muncul
- Button Detail dan Edit ada
c. Test Filter
- Klik filter "Programming"
- URL berubah ke:
/buku/kategori/Programming - Hanya buku kategori Programming yang muncul
- Test filter kategori lainnya
5. PRAKTIKUM 4: View Detail Buku (Show)
Tujuan
Membuat halaman detail buku yang menampilkan informasi lengkap.
Langkah-langkah
a. Buat View Show
File: resources/views/buku/show.blade.php
@extends('layouts.app')
@section('title', $buku->judul)
@section('content')
<div class="row">
{{-- Breadcrumb --}}
<div class="col-12 mb-3">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="{{ route('home') }}">Home</a></li>
<li class="breadcrumb-item"><a href="{{ route('buku.index') }}">Buku</a></li>
<li class="breadcrumb-item active">{{ $buku->judul }}</li>
</ol>
</nav>
</div>
</div>
<div class="row">
{{-- Kolom Kiri: Info Buku --}}
<div class="col-md-8">
<div class="card">
<div class="card-header bg-primary text-white">
<h4 class="mb-0">
<i class="bi bi-book"></i>
Detail Buku
</h4>
</div>
<div class="card-body">
{{-- Judul --}}
<h2 class="mb-3">{{ $buku->judul }}</h2>
{{-- Badge Kategori --}}
<div class="mb-3">
<span class="badge bg-{{ $buku->kategori == 'Programming' ? 'primary' : ($buku->kategori == 'Database' ? 'success' : ($buku->kategori == 'Web Design' ? 'info' : ($buku->kategori == 'Networking' ? 'warning' : 'danger'))) }} fs-6">
<i class="bi bi-tag"></i> {{ $buku->kategori }}
</span>
</div>
{{-- Informasi Detail --}}
<table class="table table-borderless">
<tr>
<td width="200" class="fw-bold">
<i class="bi bi-upc text-primary"></i> Kode Buku
</td>
<td>: {{ $buku->kode_buku }}</td>
</tr>
<tr>
<td class="fw-bold">
<i class="bi bi-person text-primary"></i> Pengarang
</td>
<td>: {{ $buku->pengarang }}</td>
</tr>
<tr>
<td class="fw-bold">
<i class="bi bi-building text-primary"></i> Penerbit
</td>
<td>: {{ $buku->penerbit }}</td>
</tr>
<tr>
<td class="fw-bold">
<i class="bi bi-calendar text-primary"></i> Tahun Terbit
</td>
<td>: {{ $buku->tahun_terbit }}</td>
</tr>
@if ($buku->isbn)
<tr>
<td class="fw-bold">
<i class="bi bi-hash text-primary"></i> ISBN
</td>
<td>: {{ $buku->isbn }}</td>
</tr>
@endif
<tr>
<td class="fw-bold">
<i class="bi bi-translate text-primary"></i> Bahasa
</td>
<td>: {{ $buku->bahasa }}</td>
</tr>
<tr>
<td class="fw-bold">
<i class="bi bi-cash text-primary"></i> Harga
</td>
<td>: <span class="text-success fs-5 fw-bold">{{ $buku->harga_format }}</span></td>
</tr>
<tr>
<td class="fw-bold">
<i class="bi bi-boxes text-primary"></i> Stok
</td>
<td>
: <span class="fw-bold">{{ $buku->stok }}</span> buku
@if ($buku->stok > 0)
<span class="badge bg-success ms-2">
<i class="bi bi-check-circle"></i> Tersedia
</span>
@else
<span class="badge bg-danger ms-2">
<i class="bi bi-x-circle"></i> Habis
</span>
@endif
</td>
</tr>
</table>
{{-- Deskripsi --}}
@if ($buku->deskripsi)
<hr>
<h5><i class="bi bi-file-text text-primary"></i> Deskripsi</h5>
<p class="text-justify">{{ $buku->deskripsi }}</p>
@else
<hr>
<p class="text-muted fst-italic">
<i class="bi bi-info-circle"></i> Tidak ada deskripsi untuk buku ini
</p>
@endif
{{-- Timestamps --}}
<hr>
<div class="row text-muted small">
<div class="col-md-6">
<i class="bi bi-clock"></i>
Ditambahkan: {{ $buku->created_at->format('d M Y H:i') }}
</div>
<div class="col-md-6 text-end">
<i class="bi bi-clock-history"></i>
Terakhir Update: {{ $buku->updated_at->format('d M Y H:i') }}
</div>
</div>
</div>
</div>
</div>
{{-- Kolom Kanan: Actions & Info Tambahan --}}
<div class="col-md-4">
{{-- Card Actions --}}
<div class="card mb-3">
<div class="card-header bg-secondary text-white">
<h6 class="mb-0">
<i class="bi bi-gear"></i> Aksi
</h6>
</div>
<div class="card-body d-grid gap-2">
<a href="{{ route('buku.edit', $buku->id) }}" class="btn btn-warning">
<i class="bi bi-pencil"></i> Edit Buku
</a>
@if ($buku->stok > 0)
<button class="btn btn-success">
<i class="bi bi-cart-plus"></i> Pinjam Buku
</button>
@else
<button class="btn btn-secondary" disabled>
<i class="bi bi-x-circle"></i> Stok Habis
</button>
@endif
<a href="{{ route('buku.index') }}" class="btn btn-outline-primary">
<i class="bi bi-arrow-left"></i> Kembali
</a>
<hr>
<form action="{{ route('buku.destroy', $buku->id) }}" method="POST" onsubmit="return confirm('Yakin ingin menghapus buku ini?')">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-danger w-100">
<i class="bi bi-trash"></i> Hapus Buku
</button>
</form>
</div>
</div>
{{-- Card Status Stok --}}
<div class="card mb-3">
<div class="card-header bg-info text-white">
<h6 class="mb-0">
<i class="bi bi-info-circle"></i> Status Stok
</h6>
</div>
<div class="card-body">
@if ($buku->stok == 0)
<div class="alert alert-danger mb-0">
<i class="bi bi-exclamation-triangle"></i>
<strong>Stok Habis!</strong><br />
Buku ini sedang tidak tersedia.
</div>
@elseif ($buku->stok <= 5)
<div class="alert alert-warning mb-0">
<i class="bi bi-exclamation-circle"></i>
<strong>Stok Menipis!</strong><br />
Tersisa {{ $buku->stok }} buku.
</div>
@else
<div class="alert alert-success mb-0">
<i class="bi bi-check-circle"></i>
<strong>Stok Aman!</strong><br />
Tersedia {{ $buku->stok }} buku.
</div>
@endif
</div>
</div>
{{-- Card Buku Serupa --}}
<div class="card">
<div class="card-header bg-dark text-white">
<h6 class="mb-0">
<i class="bi bi-collection"></i> Buku Serupa
</h6>
</div>
<div class="card-body">
@php
$bukuSerupa = App\Models\Buku::where('kategori', $buku->kategori)
->where('id', '!=', $buku->id)
->take(3)
->get();
@endphp
@forelse ($bukuSerupa as $item)
<div class="mb-3">
<a href="{{ route('buku.show', $item->id) }}" class="text-decoration-none">
<h6 class="mb-1">{{ Str::limit($item->judul, 40) }}</h6>
</a>
<small class="text-muted">{{ $item->pengarang }}</small>
</div>
@if (!$loop->last)
<hr>
@endif
@empty
<p class="text-muted small mb-0">
<i class="bi bi-info-circle"></i>
Tidak ada buku serupa
</p>
@endforelse
</div>
</div>
</div>
</div>
@endsectionb. Test View
- Dari halaman index, klik "Detail" pada salah satu buku
- URL:
http://localhost:8000/buku/1 - Verifikasi:
- Breadcrumb muncul
- Informasi lengkap buku tampil
- Badge kategori dengan warna
- Status stok dengan alert
- Button action (Edit, Pinjam, Hapus, Kembali)
- Card buku serupa muncul
6. PRAKTIKUM 5: Membuat AnggotaController & View
Tujuan
Membuat controller dan view untuk data anggota dengan konsep yang sama.
Langkah-langkah
a. Generate AnggotaController
php artisan make:controller AnggotaController --resourceb. Edit AnggotaController
File: app/Http/Controllers/AnggotaController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Anggota;
class AnggotaController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
$anggotas = Anggota::latest()->get();
// Statistik
$totalAnggota = Anggota::count();
$anggotaAktif = Anggota::where('status', 'Aktif')->count();
$anggotaNonaktif = Anggota::where('status', 'Nonaktif')->count();
return view('anggota.index', compact(
'anggotas',
'totalAnggota',
'anggotaAktif',
'anggotaNonaktif'
));
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
$anggota = Anggota::findOrFail($id);
return view('anggota.show', compact('anggota'));
}
// Methods lainnya akan diimplementasi di pertemuan 13
public function create() { }
public function store(Request $request) { }
public function edit(string $id) { }
public function update(Request $request, string $id) { }
public function destroy(string $id) { }
}c. Buat View Index Anggota
File: resources/views/anggota/index.blade.php
@extends('layouts.app')
@section('title', 'Daftar Anggota')
@section('content')
<div class="d-flex justify-content-between align-items-center mb-4">
<h1>
<i class="bi bi-people"></i>
Daftar Anggota
</h1>
<a href="{{ route('anggota.create') }}" class="btn btn-success">
<i class="bi bi-plus-circle"></i> Tambah Anggota
</a>
</div>
{{-- Statistik --}}
<div class="row mb-4">
<div class="col-md-4">
<div class="card border-success">
<div class="card-body">
<div class="d-flex justify-content-between">
<div>
<h6 class="text-muted">Total Anggota</h6>
<h2>{{ $totalAnggota }}</h2>
</div>
<i class="bi bi-people-fill text-success" style="font-size: 3rem;"></i>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card border-primary">
<div class="card-body">
<div class="d-flex justify-content-between">
<div>
<h6 class="text-muted">Anggota Aktif</h6>
<h2>{{ $anggotaAktif }}</h2>
</div>
<i class="bi bi-person-check-fill text-primary" style="font-size: 3rem;"></i>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card border-secondary">
<div class="card-body">
<div class="d-flex justify-content-between">
<div>
<h6 class="text-muted">Anggota Nonaktif</h6>
<h2>{{ $anggotaNonaktif }}</h2>
</div>
<i class="bi bi-person-x-fill text-secondary" style="font-size: 3rem;"></i>
</div>
</div>
</div>
</div>
</div>
{{-- Tabel Anggota --}}
<div class="card">
<div class="card-body">
<div class="table-responsive">
<table class="table table-hover">
<thead class="table-light">
<tr>
<th>No</th>
<th>Kode</th>
<th>Nama</th>
<th>Email</th>
<th>Telepon</th>
<th>Jenis Kelamin</th>
<th>Status</th>
<th>Aksi</th>
</tr>
</thead>
<tbody>
@forelse ($anggotas as $anggota)
<tr>
<td>{{ $loop->iteration }}</td>
<td>
<code>{{ $anggota->kode_anggota }}</code>
</td>
<td>
<strong>{{ $anggota->nama }}</strong>
</td>
<td>
<i class="bi bi-envelope"></i>
{{ $anggota->email }}
</td>
<td>
<i class="bi bi-telephone"></i>
{{ $anggota->telepon }}
</td>
<td>
@if ($anggota->jenis_kelamin == 'Laki-laki')
<i class="bi bi-gender-male text-primary"></i>
@else
<i class="bi bi-gender-female text-danger"></i>
@endif
{{ $anggota->jenis_kelamin }}
</td>
<td>
@if ($anggota->status == 'Aktif')
<span class="badge bg-success">
<i class="bi bi-check-circle"></i> Aktif
</span>
@else
<span class="badge bg-secondary">
<i class="bi bi-x-circle"></i> Nonaktif
</span>
@endif
</td>
<td>
<div class="btn-group" role="group">
<a href="{{ route('anggota.show', $anggota->id) }}"
class="btn btn-sm btn-info text-white"
title="Detail">
<i class="bi bi-eye"></i>
</a>
<a href="{{ route('anggota.edit', $anggota->id) }}"
class="btn btn-sm btn-warning"
title="Edit">
<i class="bi bi-pencil"></i>
</a>
</div>
</td>
</tr>
@empty
<tr>
<td colspan="8" class="text-center text-muted">
<i class="bi bi-inbox"></i>
Tidak ada data anggota
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
</div>
@endsectiond. Buat View Show Anggota
File: resources/views/anggota/show.blade.php
@extends('layouts.app')
@section('title', $anggota->nama)
@section('content')
<div class="row">
<div class="col-12 mb-3">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="{{ route('home') }}">Home</a></li>
<li class="breadcrumb-item"><a href="{{ route('anggota.index') }}">Anggota</a></li>
<li class="breadcrumb-item active">{{ $anggota->nama }}</li>
</ol>
</nav>
</div>
</div>
<div class="row">
<div class="col-md-8">
<div class="card">
<div class="card-header bg-success text-white">
<h4 class="mb-0">
<i class="bi bi-person"></i>
Detail Anggota
</h4>
</div>
<div class="card-body">
<div class="text-center mb-4">
@if ($anggota->jenis_kelamin == 'Laki-laki')
<i class="bi bi-person-circle text-primary" style="font-size: 5rem;"></i>
@else
<i class="bi bi-person-circle text-danger" style="font-size: 5rem;"></i>
@endif
<h3 class="mt-2">{{ $anggota->nama }}</h3>
@if ($anggota->status == 'Aktif')
<span class="badge bg-success">
<i class="bi bi-check-circle"></i> Anggota Aktif
</span>
@else
<span class="badge bg-secondary">
<i class="bi bi-x-circle"></i> Nonaktif
</span>
@endif
</div>
<table class="table table-borderless">
<tr>
<td width="200" class="fw-bold">
<i class="bi bi-upc text-success"></i> Kode Anggota
</td>
<td>: <code>{{ $anggota->kode_anggota }}</code></td>
</tr>
<tr>
<td class="fw-bold">
<i class="bi bi-envelope text-success"></i> Email
</td>
<td>: {{ $anggota->email }}</td>
</tr>
<tr>
<td class="fw-bold">
<i class="bi bi-telephone text-success"></i> Telepon
</td>
<td>: {{ $anggota->telepon }}</td>
</tr>
<tr>
<td class="fw-bold">
<i class="bi bi-geo-alt text-success"></i> Alamat
</td>
<td>: {{ $anggota->alamat }}</td>
</tr>
<tr>
<td class="fw-bold">
<i class="bi bi-calendar text-success"></i> Tanggal Lahir
</td>
<td>: {{ $anggota->tanggal_lahir->format('d F Y') }} ({{ $anggota->umur }} tahun)</td>
</tr>
<tr>
<td class="fw-bold">
<i class="bi bi-gender-ambiguous text-success"></i> Jenis Kelamin
</td>
<td>: {{ $anggota->jenis_kelamin }}</td>
</tr>
<tr>
<td class="fw-bold">
<i class="bi bi-briefcase text-success"></i> Pekerjaan
</td>
<td>: {{ $anggota->pekerjaan ?? '-' }}</td>
</tr>
<tr>
<td class="fw-bold">
<i class="bi bi-calendar-check text-success"></i> Tanggal Daftar
</td>
<td>: {{ $anggota->tanggal_daftar->format('d F Y') }} ({{ $anggota->lama_anggota }} hari)</td>
</tr>
</table>
<hr>
<div class="row text-muted small">
<div class="col-md-6">
<i class="bi bi-clock"></i>
Ditambahkan: {{ $anggota->created_at->format('d M Y H:i') }}
</div>
<div class="col-md-6 text-end">
<i class="bi bi-clock-history"></i>
Terakhir Update: {{ $anggota->updated_at->format('d M Y H:i') }}
</div>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card mb-3">
<div class="card-header bg-secondary text-white">
<h6 class="mb-0">
<i class="bi bi-gear"></i> Aksi
</h6>
</div>
<div class="card-body d-grid gap-2">
<a href="{{ route('anggota.edit', $anggota->id) }}" class="btn btn-warning">
<i class="bi bi-pencil"></i> Edit Anggota
</a>
<a href="{{ route('anggota.index') }}" class="btn btn-outline-success">
<i class="bi bi-arrow-left"></i> Kembali
</a>
<hr>
<form action="{{ route('anggota.destroy', $anggota->id) }}" method="POST" onsubmit="return confirm('Yakin ingin menghapus?')">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-danger w-100">
<i class="bi bi-trash"></i> Hapus Anggota
</button>
</form>
</div>
</div>
</div>
</div>
@endsectione. Test AnggotaController
- Akses:
http://localhost:8000/anggota - Verifikasi halaman index anggota
- Klik detail salah satu anggota
- Verifikasi halaman show anggota
E. TUGAS
Tugas 1: Membuat Halaman Dashboard (30%)
Instruksi: Buat halaman dashboard yang menampilkan ringkasan statistik perpustakaan.
Spesifikasi:
- Controller: Buat
DashboardControllerdengan methodindex() - Route:
/dashboard - Data yang ditampilkan:
- Total buku, buku tersedia, buku habis
- Total anggota, anggota aktif, anggota nonaktif
- List 5 buku terbaru
- List 5 anggota terbaru
- Quick links ke menu utama
Tugas 2: Blade Component untuk Card Buku (40%)
Instruksi: Buat Blade Component reusable untuk menampilkan card buku.
Spesifikasi:
- Generate Component:
php artisan make:component BukuCard-
Component Properties:
$buku(object Buku)$showActions(boolean, default true)
-
Component Design:
- Tampilkan: cover (icon), judul, pengarang, harga, stok
- Badge kategori
- Status ketersediaan
- Button actions (Detail, Edit) jika
$showActions = true
Tugas 3: Search & Filter Buku Advanced (30%)
Instruksi: Tambahkan fitur pencarian dan filter advanced untuk buku.
Spesifikasi:
-
Form Search:
- Input keyword (search judul, pengarang, penerbit)
- Filter kategori (dropdown)
- Filter tahun (dropdown)
- Filter ketersediaan (Semua/Tersedia/Habis)
-
Controller Method di BukuController:
public function search(Request $request)
{
$query = Buku::query();
// Filter implementation
$bukus = $query->latest()->get();
return view('buku.index', compact('bukus'));
}- Route:
/buku/search
Submission:
- Format: Link repository GitHub (sertakan screenshot di README)
- Deadline: Pertemuan 12
- Upload ke: Ngaji UIN Gusdur (submit link repository GitHub)
F. EVALUASI
1. Kuis Singkat
Pilihan Ganda:
-
Di MVC, komponen yang menangani logika aplikasi adalah:
- A. Model
- B. View
- C. Controller
- D. Router
-
Method controller untuk menampilkan detail data adalah:
- A.
index() - B.
show() - C.
detail() - D.
display()
- A.
-
Blade directive untuk looping data adalah:
- A.
@loop - B.
@for - C.
@foreach - D. Semua benar
- A.
-
Cara passing data ke view dengan compact:
- A.
compact('data') - B.
compact($data) - C.
compact->data - D.
compact(['data'])
- A.
-
Directive untuk extend layout adalah:
- A.
@include - B.
@extends - C.
@layout - D.
@inherit
- A.
-
Cara menampilkan data di Blade (escaped):
- A.
<?php echo $data ?> - B.
{!! $data !!} - C.
{{ $data }} - D.
@echo $data
- A.
-
Named route dibuat dengan:
- A.
Route::name('nama') - B.
->name('nama') - C.
->named('nama') - D.
as => 'nama'
- A.
-
Resource routing membuat berapa routes:
- A. 5
- B. 6
- C. 7
- D. 8
-
$loop->firstdigunakan untuk:- A. Item pertama loop
- B. Loop pertama
- C. Index pertama
- D. First data
-
Cara include partial view:
- A.
@include('path.file') - B.
@partial('path.file') - C.
@import('path.file') - D.
@require('path.file')
- A.
Essay:
-
Jelaskan alur kerja MVC di Laravel ketika user mengakses
/buku! (15 poin) -
Apa perbedaan
@yielddan@sectiondi Blade? Berikan contoh! (10 poin) -
Sebutkan 5 Blade directives dan fungsinya! (10 poin)
-
Buatlah route resource untuk
TransaksiController! (10 poin) -
Apa keuntungan menggunakan layout inheritance di Blade? (10 poin)
2. Checklist Kompetensi
| No | Kompetensi | Belum | Cukup | Mahir |
|---|---|---|---|---|
| 1 | Memahami konsep MVC | â | â | â |
| 2 | Membuat Controller | â | â | â |
| 3 | Setup routing | â | â | â |
| 4 | Passing data ke View | â | â | â |
| 5 | Menggunakan Blade directives | â | â | â |
| 6 | Layout inheritance | â | â | â |
| 7 | Blade components | â | â | â |
| 8 | Named routes | â | â | â |
| 9 | Query data dari Model | â | â | â |
| 10 | Menampilkan data di View | â | â | â |
G. REFERENSI
1. Dokumentasi Laravel 12
- Controllers: https://laravel.com/docs/12.x/controllers (opens in a new tab)
- Blade Templates: https://laravel.com/docs/12.x/blade (opens in a new tab)
- Routing: https://laravel.com/docs/12.x/routing (opens in a new tab)
- Views: https://laravel.com/docs/12.x/views (opens in a new tab)
2. Bootstrap 5
- Components: https://getbootstrap.com/docs/5.3/components/ (opens in a new tab)
- Icons: https://icons.getbootstrap.com/ (opens in a new tab)
3. Tutorial Laravel
- Laravel Daily - Controllers Best Practices
- Laracasts - Blade Mastery
- Laravel News - MVC Pattern
H. PERSIAPAN PERTEMUAN 12
Topik: CRUD Buku dengan Laravel
Preview:
- Form create & validation
- Store data ke database
- Form edit & update
- Delete data
- Flash messages
- Form Request validation
Yang Perlu Disiapkan:
- Controller & View sudah jalan
- Pahami form handling
- Study validation rules Laravel
- Siapkan browser untuk testing
Pre-reading:
- Form Validation: https://laravel.com/docs/12.x/validation (opens in a new tab)
- Form Requests: https://laravel.com/docs/12.x/validation#form-request-validation (opens in a new tab)
Selamat Belajar! đđģ
End of Module - Pertemuan 11
Next: Pertemuan 12 - CRUD Buku dengan Laravel