Pendahuluan — dari Capstone ke ubah & hapus
Artikel ini adalah #61 (ini) — pembuka Seri 5: Laravel Lanjutan (di roadmap sering disebut Framework-based). Bukan loncat stack baru: kita memperdalam pola yang sama di domain perpustakaan mini.
Di Capstone API Perpustakaan Laravel (#60) kamu sudah punya tiga pintu: baca katalog (publik), login staf, dan tambah buku (wajib bukti masuk). Sekarang kita lengkapi CRUD buku: ubah dan hapus.
Awam: CRUD = Create · Read · Update · Delete — buat, baca, ubah, hapus. Capstone sudah Create + Read. Artikel ini fokus Update + Delete. Masih satu rak buku; belum pinjam/kembali (itu nanti).
Prasyarat: sudah baca Capstone (#60) — paham route, bukti masuk,
401/422/201. Pakai Laravel 11+.
Spesifikasi fitur — apa yang kita bangun?
Daftar singkat yang bisa dijelaskan ke teman:
- Ubah buku — wajib bukti masuk. ID tidak ketemu =
404; isian kotor =422; sukses =200. - Hapus buku — wajib bukti masuk. ID tidak ketemu =
404; sukses =204(atau200+ pesan singkat). - Katalog & tambah — tetap seperti Capstone (tidak diulang panjang di sini).
Awam: 404 = “tidak ketemu di rak”. Beda dengan 401 (belum diizinkan) dan 422 (isian belum rapi).
Istilah — ringkas untuk ubah & hapus
| Istilah | Arti awam | Catatan |
|---|---|---|
| CRUD | Empat kerja dasar data: buat · baca · ubah · hapus | Bukan nama file Laravel |
PUT / PATCH |
Metode HTTP untuk ubah data yang sudah ada | Di sini kita pakai PUT sederhana |
DELETE |
Metode HTTP untuk menghapus | Wajib bukti masuk di Capstone-lanjutan ini |
404 |
ID / buku tidak ketemu | Bukan salah sandi |
204 |
Sukses hapus; tubuh jawaban boleh kosong | Boleh juga 200 + JSON — pilih satu gaya |
Urutan tetap: cek bukti -> cari buku -> cek isian (untuk ubah) -> simpan/hapus -> jawab JSON.
Kenapa PHP biasa dulu?
Ide “ubah baris di rak” dan “buang baris dari rak” lebih mudah dirasakan tanpa framework. Kalau alurnya klik, cuplikan Laravel terasa bungkus yang sama.
<?php
// Mini ubah buku: tanpa bukti = 401; ID tidak ketemu = 404.
$buktiValid = "kartu-abc123";
$buktiDariHeader = "";
$katalog = [
1 => ["judul" => "Dasar PHP", "tahun" => 2023],
];
$id = 1;
$isian = ["judul" => "Dasar PHP Revisi", "tahun" => 2024];
header("Content-Type: application/json; charset=utf-8");
if ($buktiDariHeader === "" || $buktiDariHeader !== $buktiValid) {
http_response_code(401);
echo json_encode(["pesan" => "Belum diizinkan — bawa bukti masuk"], JSON_UNESCAPED_UNICODE), PHP_EOL;
exit;
}
if (! isset($katalog[$id])) {
http_response_code(404);
echo json_encode(["pesan" => "Buku tidak ketemu"], JSON_UNESCAPED_UNICODE), PHP_EOL;
exit;
}
echo json_encode(["ok" => true, "catatan" => "siap ubah"], JSON_UNESCAPED_UNICODE), PHP_EOL;
Output:
{"pesan":"Belum diizinkan — bawa bukti masuk"}
Awam: contoh ini sengaja tanpa bukti agar kamu lihat pintu 401 dulu. Di demo lengkap nanti, bukti diisi.
Alur ubah buku — PHP sederhana
Setelah login (lihat Capstone (#60)), pemanggil — aplikasi atau alat yang memanggil API — membawa bukti dan ID buku.
<?php
$buktiValid = "kartu-abc123";
$buktiDariHeader = "kartu-abc123";
$katalog = [
1 => ["judul" => "Dasar PHP", "tahun" => 2023],
];
$id = 1;
$isian = ["judul" => "Dasar PHP Revisi", "tahun" => 2024];
header("Content-Type: application/json; charset=utf-8");
if ($buktiDariHeader !== $buktiValid) {
http_response_code(401);
echo json_encode(["pesan" => "Belum diizinkan — bawa bukti masuk"], JSON_UNESCAPED_UNICODE), PHP_EOL;
exit;
}
if (! isset($katalog[$id])) {
http_response_code(404);
echo json_encode(["pesan" => "Buku tidak ketemu"], JSON_UNESCAPED_UNICODE), PHP_EOL;
exit;
}
$judul = trim((string) ($isian["judul"] ?? ""));
$tahun = $isian["tahun"] ?? null;
if ($judul === "" || ! is_int($tahun)) {
http_response_code(422);
echo json_encode(["pesan" => "Isian belum rapi"], JSON_UNESCAPED_UNICODE), PHP_EOL;
exit;
}
$katalog[$id] = ["judul" => $judul, "tahun" => $tahun];
http_response_code(200);
echo json_encode(["ok" => true, "buku" => $katalog[$id]], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT), PHP_EOL;
Output (bentuknya mirip):
{
"ok": true,
"buku": {
"judul": "Dasar PHP Revisi",
"tahun": 2024
}
}
Awam: urutan penting. Cek bukti dulu, baru cari ID, baru validasi isian — supaya orang asing tidak “menguji” rak dan aturan isian.
Laravel — cuplikan ubah & hapus (bukan file mandiri)
Di proyek Laravel, ide yang sama tersebar di route + controller + Form Request + service. Cuplikan di bawah bukan dijalankan dengan php file.php:
<?php
// Cuplikan Laravel (bukan file mandiri) — ubah & hapus terlindungi.
use App\Http\Controllers\BukuController;
use Illuminate\Support\Facades\Route;
Route::put('/api/buku/{id}', [BukuController::class, 'update'])
->middleware('auth:sanctum'); // pemeriksa pintu
Route::delete('/api/buku/{id}', [BukuController::class, 'destroy'])
->middleware('auth:sanctum');
Awam:
update= fungsi ubah; dijaga pemeriksa pintu (middlewareauth:sanctum)destroy= fungsi hapus; nama umum di Laravel untuk “buang data”{id}= nomor buku di URL — seperti nomor loker di rak
<?php
// Cuplikan Laravel — controller tipis memanggil service.
namespace App\Http\Controllers;
use App\Http\Requests\UpdateBookRequest;
use App\Services\BukuService;
use Illuminate\Http\JsonResponse;
class BukuController extends Controller
{
public function __construct(private BukuService $bukuService)
{
}
public function update(UpdateBookRequest $request, int $id): JsonResponse
{
$buku = $this->bukuService->ubah($id, $request->validated());
if ($buku === null) {
return response()->json(['pesan' => 'Buku tidak ketemu'], 404);
}
return response()->json(['ok' => true, 'buku' => $buku], 200);
}
public function destroy(int $id): JsonResponse
{
$ok = $this->bukuService->hapus($id);
if (! $ok) {
return response()->json(['pesan' => 'Buku tidak ketemu'], 404);
}
return response()->json(null, 204);
}
}
Awam: UpdateBookRequest = penjaga isian untuk ubah. validated() = ambil isian yang sudah lolos. BukuService = pekerja yang menyimpan/menghapus (Eloquent di dalamnya). JsonResponse = tipe jawaban “ini JSON” — boleh diabaikan dulu. Baris private BukuService $bukuService = Laravel menyiapkan layanan otomatis (tidak perlu new manual).
Pola Dasar — ubah & hapus buku
-
1
Mulai dari Capstone
Pastikan baca + login + tambah sudah “klik” di Capstone (#60). -
2
Pasang route ubah & hapus
PUTdanDELETEdengan pemeriksa pintu. -
3
Cari ID dulu
Tidak ketemu =404— jangan pura-pura sukses. -
4
Jaga isian saat ubah
Form Request / validasi — kotor =422. -
5
Service tipis
Controller minta pekerja; Eloquent di dalam service. -
6
Uji empat jalur
Tanpa bukti · ID palsu · isian kotor · sukses ubah/hapus.
Kode lengkap — demo mandiri ubah & hapus
Simpan sebagai laravel_crud_buku_ubah_hapus_demo.php, lalu jalankan php laravel_crud_buku_ubah_hapus_demo.php:
<?php
declare(strict_types=1);
$buktiAktif = "kartu-abc123";
$katalog = [
1 => ["judul" => "Dasar PHP", "tahun" => 2023],
2 => ["judul" => "Belajar Laravel", "tahun" => 2024],
];
function ubahBuku(?string $buktiHeader, string $buktiAktif, int $id, array $isian, array &$katalog): array
{
if ($buktiHeader === null || $buktiHeader === "" || $buktiHeader !== $buktiAktif) {
return ["status" => 401, "body" => ["pesan" => "Belum diizinkan — bawa bukti masuk"]];
}
if (! isset($katalog[$id])) {
return ["status" => 404, "body" => ["pesan" => "Buku tidak ketemu"]];
}
$judul = trim((string) ($isian["judul"] ?? ""));
$tahun = $isian["tahun"] ?? null;
if ($judul === "" || ! is_int($tahun)) {
return ["status" => 422, "body" => ["pesan" => "Isian belum rapi"]];
}
$katalog[$id] = ["judul" => $judul, "tahun" => $tahun];
return ["status" => 200, "body" => ["ok" => true, "buku" => $katalog[$id]]];
}
function hapusBuku(?string $buktiHeader, string $buktiAktif, int $id, array &$katalog): array
{
if ($buktiHeader === null || $buktiHeader === "" || $buktiHeader !== $buktiAktif) {
return ["status" => 401, "body" => ["pesan" => "Belum diizinkan — bawa bukti masuk"]];
}
if (! isset($katalog[$id])) {
return ["status" => 404, "body" => ["pesan" => "Buku tidak ketemu"]];
}
unset($katalog[$id]);
return ["status" => 204, "body" => null];
}
function demo(string $judul, callable $aksi): void
{
echo "=== {$judul} ===", PHP_EOL;
$hasil = $aksi();
echo "status: ", $hasil["status"], PHP_EOL;
if ($hasil["body"] === null) {
echo "(tubuh kosong — cocok untuk 204)", PHP_EOL, PHP_EOL;
return;
}
echo json_encode($hasil["body"], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT), PHP_EOL, PHP_EOL;
}
demo("Ubah tanpa bukti -> 401", function () use ($buktiAktif, &$katalog) {
return ubahBuku(null, $buktiAktif, 1, ["judul" => "X", "tahun" => 2025], $katalog);
});
demo("Ubah ID palsu -> 404", function () use ($buktiAktif, &$katalog) {
return ubahBuku($buktiAktif, $buktiAktif, 99, ["judul" => "X", "tahun" => 2025], $katalog);
});
demo("Ubah isian kotor -> 422", function () use ($buktiAktif, &$katalog) {
return ubahBuku($buktiAktif, $buktiAktif, 1, ["judul" => "", "tahun" => "dua"], $katalog);
});
demo("Ubah bersih -> 200", function () use ($buktiAktif, &$katalog) {
return ubahBuku($buktiAktif, $buktiAktif, 1, ["judul" => "Dasar PHP Revisi", "tahun" => 2025], $katalog);
});
demo("Hapus bersih -> 204", function () use ($buktiAktif, &$katalog) {
return hapusBuku($buktiAktif, $buktiAktif, 2, $katalog);
});
Awam: demo(...) hanya membungkus output di terminal. callable = sesuatu yang bisa dipanggil seperti fungsi. declare(strict_types=1); membuat tipe lebih ketat — boleh diikuti, tidak wajib dihafal. Alur penting: tanpa bukti, ID palsu, isian kotor, sukses ubah, sukses hapus.
Kesalahan umum
| Gejala | Penyebab tipikal | Perbaikan awam |
|---|---|---|
| Bingung 401 vs 404 | Mencampur “belum diizinkan” dengan “tidak ketemu” | 401 = identitas; 404 = ID kosong di rak |
| Ubah publik tanpa bukti | Lupa pemeriksa pintu (middleware) |
Kunci PUT/DELETE seperti kunci POST tambah |
| Hapus sukses tapi data masih ada | Salah ID atau belum dihapus di service (di PHP demo: unset = buang dari daftar) |
Uji ulang dengan demo; cek ID yang sama |
| Controller membengkak | Validasi + cari + hapus digabung satu fungsi | Form Request + Service + controller tipis |
Latihan singkat
- Ubah demo: tambah kasus “hapus tanpa bukti” dan pastikan tetap
401. - Jelaskan ke teman: beda
404dan422dengan analogi rak buku. - Tulis satu kalimat: kenapa ubah/hapus tidak boleh publik seperti baca katalog.
FAQ singkat
Haruskah pakai PUT atau PATCH?
Untuk belajar, PUT (ganti data buku yang dikirim) sudah cukup. PATCH biasanya untuk ubah sebagian — boleh dipelajari setelah alur ini jelas.
Kenapa 204 tubuhnya kosong?
Artinya “sukses, tidak ada JSON yang perlu dibaca”. Kalau kamu lebih nyaman 200 + {"ok": true}, itu juga valid — pilih satu gaya dan konsisten.
Ke mana setelah ini?
Berikutnya alami: relasi Eloquent (anggota & peminjaman) — masih Laravel lanjutan, belum Capstone pinjam-kembali. Belum perlu hardlink; tunggu artikel berikutnya LIVE.
Kesimpulan
Kamu sudah melengkapi CRUD buku: Capstone memberi baca + tambah; #61 (ini) menambah ubah dan hapus dengan urutan bukti -> cari ID -> validasi -> kerja service. Status baru yang penting: 404 dan 204.
Seri 5 progress: langkah #61 (ini) · 1/8 Laravel Lanjutan · prasyarat: Capstone (#60) LIVE. Berikutnya: Relasi Eloquent (anggota & peminjaman) — soft, belum hardlink.