Pendahuluan — kenapa capstone setelah enam artikel sebelumnya

Artikel ini adalah #70 (ini) di Seri 5: Laravel Lanjutan — langkah penutup seri. Setelah Rate Limiting API (#69) melindungi API pinjam dari spam, saatnya menyatukan semua potongan ke satu alur utuh: anggota pinjam buku, lihat daftar pinjam, lalu kembalikan.

Bayangkan petugas perpustakaan yang menyelesaikan satu shift lengkap — dari slip pinjam baru sampai buku kembali ke rak. Capstone ini menggabungkan fondasi dari Relasi Eloquent: Anggota & Peminjaman (#64), Pagination, Filter & Pencarian (#65), Authorization Policy: Siapa Boleh Ubah (#66), API Resource: Rapikan Bentuk JSON (#67), Feature Test API (#68), dan Rate Limiting API (#69).

Awam: enam artikel sebelumnya seperti belajar potongan puzzle. Hari ini kamu merakit puzzle itu jadi gambar utuh — alur pinjam, daftar, kembalikan — tanpa memulai dari nol.

Prasyarat: sudah selesai Rate Limiting API (#69) dan fondasi Instal PHP, Composer & Proyek Laravel (#56) / Struktur Folder, .env & Artisan Laravel (#57). CRUD buku dari CRUD API Buku: Ubah & Hapus (#63) diasumsikan sudah ada. Pakai Laravel 13+ — butuh PHP 8.3+.

Spesifikasi fitur — pinjam, daftar, kembalikan

Tiga gerakan yang harus jalan berurutan:

  1. Pinjam — anggota meminjam buku; status berubah dari tersedia ke dipinjam.
  2. Daftar — petugas melihat daftar pinjam aktif (dengan pagination dan filter dari artikel sebelumnya).
  3. Kembalikan — buku dikembalikan; status kembali tersedia.

Awam: selesai artikel ini, kamu punya peta alur lengkap perpustakaan mini — bukan lagi potongan terpisah. Cuplikan Laravel di bawah merujuk ke Policy, Resource, Feature Test, dan throttle yang sudah dipelajari; fokus capstone adalah urutan yang benar.

Istilah — ringkas untuk capstone

Istilah Arti awam Catatan
Capstone Proyek penutup yang menyatukan banyak pelajaran Langkah penutup Seri 5
store Method controller untuk mencatat pinjam baru POST pinjam
index Method controller untuk menampilkan daftar GET daftar pinjam
return Method controller untuk mengembalikan buku POST atau PATCH kembalikan
Status pinjam Keadaan buku: tersedia, dipinjam, dikembalikan Inti state machine PHP di demo
Alur utuh Rangkaian pinjam -> daftar -> kembalikan tanpa lompatan Capstone menguji urutan ini

Urutan belajar kita: cek alur PHP dulu -> demo pass/fail -> baru cuplikan controller Laravel. Kalau loncat langsung ke controller tanpa paham status pinjam, kembalikan sering ditulis di waktu yang salah.

Persiapan — alat yang kamu buka

Alat yang dipakai di artikel ini (fondasi dari Instal PHP, Composer & Proyek Laravel (#56) dan Struktur Folder, .env & Artisan Laravel (#57) — tidak ada unduhan Composer baru hari ini):

  • Explorer — cek folder proyek perpustakaan-api, lalu lihat app\Http\Controllers, app\Models, routes\api.php, dan tests\Feature untuk cuplikan capstone.
  • Terminal — Laragon: menu Terminal · XAMPP: tombol Shell. Hindari CMD/PowerShell dari Start Menu kalau PATH PHP-mu belum rapi.
  • Editor teks — Notepad / VS Code — untuk membuka controller atau file demo. Contoh: notepad app\Http\Controllers\PeminjamanController.php.
  • Browser — opsional. Inti uji hari ini ada di terminal; browser berguna kalau kamu sudah menjalankan php artisan serve dan ingin bandingkan dengan curl.exe.

Awam: untuk artikel ini satu terminal sebenarnya cukup — jalankan php capstone_pinjam_kembali_laravel_demo.php di folder proyek. Kalau php artisan serve dari artikel sebelumnya masih hidup, pakai terminal kedua untuk perintah curl.exe pinjam lalu kembalikan. Kalau butuh jendela kedua: Laragon — klik menu Terminal lagi · XAMPP — klik tombol Shell lagi, lalu cd ke folder proyek yang sama.

Buka terminal Laragon/Shell XAMPP, masuk ke folder proyek:

cd C:\laragon\www\perpustakaan-api

Di XAMPP biasanya: cd C:\xampp\htdocs\perpustakaan-api. Sesuaikan kalau foldermu beda.

Install-dari-nol: kalau php atau composer belum dikenali terminal, kembali dulu ke Instal PHP, Composer & Proyek Laravel (#56). Kalau struktur folder proyek masih membingungkan, ulangi Struktur Folder, .env & Artisan Laravel (#57).

Kenapa PHP biasa dulu?

Kalau langsung loncat ke controller Laravel capstone, pemula sering bingung: kapan status boleh berubah? Maka kita mulai dari variabel status sederhana — supaya perbedaan pinjam lolos vs status salah gagal terlihat jelas sebelum dibungkus Eloquent dan Policy.

<?php
// Mini: status buku sebelum dan sesudah pinjam.
$status = 'tersedia';
echo $status === 'tersedia' ? "LOLOS" : "GAGAL", PHP_EOL;
$status = 'dipinjam';
echo $status === 'tersedia' ? "LOLOS" : "GAGAL", PHP_EOL;

Awam — cara menguji bagian ini: salin potongan di atas ke file misalnya status-cek.php, lalu di terminal Laragon/XAMPP jalankan php status-cek.php. Kalau muncul LOLOS lalu GAGAL, ide “status harus cocok sebelum aksi” sudah terlihat.

Alur pinjam–kembali — langkah demi langkah

Gerakan petugas perpustakaan yang benar selalu sama:

  1. Pinjam — cek buku tersedia, catat slip, ubah status ke dipinjam.
  2. Daftar — tampilkan slip aktif (nanti pakai pagination dari Pagination, Filter & Pencarian (#65)).
  3. Kembalikan — cek status dipinjam, ubah ke dikembalikan atau tersedia.
  4. Tolak salah urutan — kembalikan buku yang belum dipinjam harus gagal.
<?php
// Salin ke file misalnya alur-cek.php lalu jalankan: php alur-cek.php
$status = 'kosong';

function jalankanLangkah(string $aksi, string $statusSaatIni): array
{
    if ($aksi === 'pinjam' && $statusSaatIni === 'kosong') {
        return ['lolos' => true, 'statusBaru' => 'dipinjam', 'pesan' => 'pinjam ok'];
    }
    if ($aksi === 'daftar') {
        return ['lolos' => true, 'statusBaru' => $statusSaatIni, 'pesan' => 'daftar ok'];
    }
    if ($aksi === 'kembalikan' && $statusSaatIni === 'dipinjam') {
        return ['lolos' => true, 'statusBaru' => 'dikembalikan', 'pesan' => 'kembali ok'];
    }
    return ['lolos' => false, 'statusBaru' => $statusSaatIni, 'pesan' => 'status salah'];
}

$hasil = jalankanLangkah('pinjam', $status);
$status = $hasil['statusBaru'];
echo $hasil['lolos'] ? 'CEK LOLOS' : 'CEK GAGAL', ' — ', $hasil['pesan'], PHP_EOL;

$hasil = jalankanLangkah('daftar', $status);
echo $hasil['lolos'] ? 'CEK LOLOS' : 'CEK GAGAL', ' — ', $hasil['pesan'], PHP_EOL;

$hasil = jalankanLangkah('kembalikan', $status);
$status = $hasil['statusBaru'];
echo $hasil['lolos'] ? 'CEK LOLOS' : 'CEK GAGAL', ' — ', $hasil['pesan'], PHP_EOL;

$hasil = jalankanLangkah('kembalikan', $status);
echo $hasil['lolos'] ? 'CEK LOLOS' : 'CEK GAGAL', ' — ', $hasil['pesan'], PHP_EOL;

Awam — cara menguji bagian ini: salin potongan di atas ke alur-cek.php, lalu di terminal jalankan php alur-cek.php. Harusnya tiga baris CEK LOLOS lalu satu CEK GAGAL — status salah. Ini versi PHP murni dari alur capstone sebelum cuplikan controller Laravel.

Pinjam -> Daftar -> Kembalikan (capstone Seri 5) Pinjam POST store Daftar GET index Kembalikan POST return Selesai status ok Policy, Resource, Feature Test, dan throttle melindungi tiap langkah. Capstone menyatukan potongan Relasi sampai Rate Limiting ke satu alur petugas.
#70 (ini) menutup Seri 5 dengan alur pinjam–daftar–kembalikan yang menggabungkan pelajaran dari Relasi Eloquent (#64) sampai Rate Limiting (#69).

Laravel — cuplikan capstone (bukan file mandiri)

Di proyek Laravel, tiga method controller ini melengkapi alur. Masing-masing merujuk ke artikel sebelumnya — tempel ke proyek kalau fondasi Relasi Eloquent sampai Rate Limiting sudah ada.

<?php
// Cuplikan Laravel (bukan file mandiri)
// app/Http/Controllers/PeminjamanController.php — store (pinjam)

public function store(Request $request)
{
    $this->authorize('create', Peminjaman::class); // Policy otorisasi
    $pinjam = Peminjaman::create($request->validated());
    return new PeminjamanResource($pinjam); // API Resource
}
<?php
// Cuplikan Laravel (bukan file mandiri)
// app/Http/Controllers/PeminjamanController.php — index (daftar)

public function index(Request $request)
{
    $query = Peminjaman::with(['anggota', 'buku'])->where('status', 'dipinjam');
    // pagination + filter dari artikel Pagination
    return PeminjamanResource::collection($query->paginate(10));
}
<?php
// Cuplikan Laravel (bukan file mandiri)
// app/Http/Controllers/PeminjamanController.php — returnBook (kembalikan)

public function returnBook(Request $request, int $id)
{
    $pinjam = Peminjaman::findOrFail($id);
    $this->authorize('update', $pinjam); // Policy otorisasi
    $pinjam->update(['status' => 'dikembalikan', 'dikembalikan_at' => now()]);
    return new PeminjamanResource($pinjam);
}

Pasang rute di routes\api.php — POST pinjam pakai throttle:pinjam dari Rate Limiting API (#69):

<?php
// Cuplikan Laravel (bukan file mandiri)
// routes/api.php

Route::middleware('throttle:pinjam')->post('/api/pinjam', [PeminjamanController::class, 'store']);
Route::get('/api/pinjam', [PeminjamanController::class, 'index']);
Route::post('/api/pinjam/{id}/kembalikan', [PeminjamanController::class, 'returnBook']);

Feature Test dari Feature Test API (#68) bisa memastikan alur: $response->assertJsonStructure(['data' => ['id', 'status']]) setelah pinjam, lalu assert status berubah setelah kembalikan.

Awam: cuplikan ini bukan file mandiri — gabungkan ke controller dan rute yang sudah ada. Relasi Eloquent dari Relasi Eloquent (#64) membuat with(['anggota', 'buku']) bisa membaca nama tanpa query manual.

Uji dengan curl.exe di terminal (kalau php artisan serve sudah jalan):

curl.exe -X POST "http://127.0.0.1:8000/api/pinjam" -H "Content-Type: application/json" -d "{\"buku_id\":1,\"anggota_id\":1}"
curl.exe -X POST "http://127.0.0.1:8000/api/pinjam/1/kembalikan" -H "Content-Type: application/json"

Awam: jalankan perintah pinjam dulu, lalu kembalikan. Kalau muncul 404, rute mungkin belum dipasang — itu wajar; fokus dulu ke demo PHP di atas. Kalau php artisan serve belum jalan, cukup uji demo PHP; terminal kedua hanya untuk uji curl.exe.

Pola Dasar — satu alur utuh petugas perpustakaan

  1. 1
    Cek status buku
    Hanya buku tersedia yang boleh dipinjam — mirip alur-cek.php.
  2. 2
    Catat pinjam (store)
    Policy izinkan, Resource rapikan JSON — fondasi otorisasi dan Resource.
  3. 3
    Tampilkan daftar (index)
    Pagination dan filter dari Pagination (#65).
  4. 4
    Kembalikan buku (return)
    Ubah status; tolak kalau belum pernah dipinjam.
  5. 5
    Kunci dengan Feature Test
    assertJsonStructure dari Feature Test (#68).
  6. 6
    Lindungi POST pinjam
    throttle:pinjam dari Rate Limiting (#69).

Kode lengkap — demo mandiri

Simpan sebagai capstone_pinjam_kembali_laravel_demo.php, lalu jalankan php capstone_pinjam_kembali_laravel_demo.php:

<?php
declare(strict_types=1);

function pinjam(array $buku): array
{
    if ($buku['status'] !== 'tersedia') {
        return ['lolos' => false, 'pesan' => 'buku sudah dipinjam'];
    }
    $buku['status'] = 'dipinjam';
    return ['lolos' => true, 'pesan' => 'pinjam ok', 'buku' => $buku];
}

function kembalikan(array $buku): array
{
    if ($buku['status'] !== 'dipinjam') {
        return ['lolos' => false, 'pesan' => 'belum dipinjam'];
    }
    $buku['status'] = 'tersedia';
    return ['lolos' => true, 'pesan' => 'kembali ok', 'buku' => $buku];
}

function demo(string $judul, array $buku, string $mode): void
{
    echo "=== {$judul} ===", PHP_EOL;
    if ($mode === 'pinjam') {
        $hasil = pinjam($buku);
    } else {
        $hasil = kembalikan($buku);
    }
    echo $hasil['lolos'] ? 'LOLOS' : 'GAGAL', PHP_EOL;
    echo $hasil['pesan'], PHP_EOL, PHP_EOL;
}

$bukuTersedia = ['id' => 1, 'status' => 'tersedia'];
$bukuDipinjam = ['id' => 2, 'status' => 'dipinjam'];

demo('Pinjam lolos', $bukuTersedia, 'pinjam');
demo('Kembalikan lolos', $bukuDipinjam, 'kembalikan');
demo('Status salah gagal', ['id' => 3, 'status' => 'dipinjam'], 'pinjam');

Awam — cara menguji bagian ini: simpan file sebagai capstone_pinjam_kembali_laravel_demo.php di folder proyek, lalu di terminal Laragon/XAMPP jalankan php capstone_pinjam_kembali_laravel_demo.php. Harusnya muncul dua LOLOS lalu satu GAGAL. Fungsi pinjam dan kembalikan adalah inti logika; demo(...) hanya membungkus output agar mudah dibaca di terminal.

Kesalahan umum

Gejala Penyebab tipikal Perbaikan awam
Kembalikan selalu gagal Status belum diubah saat pinjam Cek alur alur-cek.php — pinjam harus jalan dulu
Daftar kosong padahal ada pinjam Filter status salah di index Samakan string status dengan migration
403 saat pinjam Policy belum mengizinkan create Ulangi Authorization Policy (#66)
JSON berantakan Resource belum dipasang Kembali ke API Resource (#67)
curl.exe selalu 404 Rute belum dipasang atau serve belum jalan Fokus demo PHP dulu; 404 wajar kalau rute belum ada
Test capstone gagal acak Database test tidak fresh Pakai RefreshDatabase seperti di Feature Test (#68)

Latihan singkat

  1. Ubah demo: tambah skenario kembalikan buku yang belum dipinjam — harus GAGAL.
  2. Jelaskan ke teman: urutan pinjam -> daftar -> kembalikan dengan analogi petugas perpustakaan.
  3. Tulis satu kalimat: artikel Relasi Eloquent sampai Rate Limiting mana yang melindungi tiap langkah capstone.

FAQ singkat

Apakah capstone menggantikan artikel Relasi sampai Rate Limiting?
Tidak. Capstone menyatukan potongan yang sudah dipelajari. Kalau relasi atau Policy belum paham, kembali ke artikel masing-masing — jangan loncat.

Haruskah semua cuplikan Laravel langsung jalan?
Tidak wajib hari ini. Demo PHP membuktikan logika status; cuplikan controller ditempel bertahap ke proyek yang sudah punya fondasi instalasi sampai rate limiting.

Tool apa yang dibuka dulu?
Explorer untuk Controllers, Models, routes\api.php, tests\Feature; satu terminal untuk demo PHP; editor untuk cuplikan. Kalau serve hidup, terminal kedua untuk curl.exe pinjam lalu kembalikan.

Potongan sintaks diuji di mana?
Langkah tengah salin ke alur-cek.php, lalu php alur-cek.php. Demo lengkap: php capstone_pinjam_kembali_laravel_demo.php. Cuplikan Laravel ditempel ke controller dan routes\api.php; uji alur dengan curl.exe.

Ke mana setelah Seri 5?
Seri 5 selesai. Berikutnya alami: Piranti Bergerak — jalur belajar berikutnya setelah Laravel Lanjutan.

Kesimpulan

Kamu menyelesaikan capstone pinjam & kembalikan: cek alur di alur-cek.php, demo pass/fail di capstone_pinjam_kembali_laravel_demo.php, lalu cuplikan controller yang merujuk Policy, Resource, Feature Test, dan throttle dari enam artikel sebelumnya. Petugas perpustakaan digital — satu shift lengkap dari slip pinjam sampai buku kembali.

Seri 5 progress: langkah #70 (ini) · 7/7 — tamat Laravel Lanjutan · prasyarat: Rate Limiting API (#69) LIVE. Seri 5: 7/7 — tamat. Berikutnya alami: Piranti Bergerak.