Pendahuluan — slip pinjam yang rapi di JSON

Artikel ini adalah #67 (ini) di Seri 5: Laravel Lanjutan. Setelah siapa boleh ubah catatan pinjam dikunci di Authorization Policy: Siapa Boleh Ubah (#66), pertanyaan berikutnya muncul: bagaimana bentuk jawaban JSON yang dikirim ke pemanggil — aplikasi atau alat yang memanggil API?

Tanpa bentuk yang konsisten, pemanggil menerima catatan acak: kadang ada anggota_id mentah, kadang tidak; status hanya kode aktif tanpa label manusiawi. Hari ini kita belajar API Resource (bungkus Laravel untuk merapikan JSON): pilih field yang perlu, sembunyikan kolom internal, tambahkan status_label, dan kirim slip pinjam yang rapi.

Awam: bayangkan dua slip pinjam. Yang satu tulisannya rapi: judul buku, nama anggota, status jelas. Yang lain catatan acak di kertas kusut — isinya sama, tapi susah dibaca. Itu beda slip pinjam yang rapi vs catatan acak. Di Laravel, JsonResource membantu merapikan bentuk jawaban JSON.

Prasyarat: sudah selesai Authorization Policy: Siapa Boleh Ubah (#66), paham fondasi Instal PHP, Composer & Proyek Laravel (#56) / Struktur Folder, .env & Artisan Laravel (#57). Pakai Laravel 13+ — butuh PHP 8.3+.

Spesifikasi fitur — apa yang selesai hari ini?

Tiga hal ini yang kita kejar:

  1. Field konsisten — setiap catatan pinjam punya field yang sama: id, judul_buku, nama_anggota, status, status_label.
  2. Sembunyikan yang tidak perlu — kolom internal seperti anggota_id mentah tidak dikirim ke pemanggil.
  3. Satu tempat merapikan — logika bentuk JSON tidak copy-paste di banyak pengatur kode; di Laravel dipindah ke kelas PeminjamanResource.

Awam: selesai artikel ini, kamu belum menulis uji otomatis. Kamu sedang merapikan bentuk jawaban JSON slip pinjam di proyek perpustakaan mini — konsisten, tanpa kolom internal bocor. Uji otomatis datang di artikel berikutnya tentang Feature Test.

Istilah — ringkas untuk bentuk jawaban JSON

Istilah Arti awam Catatan
JsonResource / API Resource Bungkus Laravel yang merapikan satu baris data jadi JSON Kelas dengan metode toArray
toArray Perintah “ubah data jadi array siap JSON” Satu fungsi, satu bentuk
status_label Status dalam bahasa manusia Misalnya “Sedang dipinjam” / “Sudah kembali”
Field konsisten Setiap baris punya nama field yang sama Pemanggil tidak bingung membaca
collection Bungkus banyak baris sekaligus PeminjamanResource::collection(...)
Hide anggota_id Jangan kirim ID internal ke luar Pilih field di toArray, bukan kirim baris mentah

Urutan belajar kita: array PHP dulu -> rapikan manual dengan fungsi -> baru bungkus Laravel JsonResource. Kalau loncat langsung ke Resource tanpa memahami field mana yang perlu, JSON sering masih berantakan.

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\Resources dan app\Http\Controllers untuk bungkus JSON dan pengatur kode.
  • 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 Resource dan pengatur kode. Contoh: notepad app\Http\Resources\PeminjamanResource.php dan 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 uji lewat alamat URL.

Awam: untuk artikel ini satu terminal sebenarnya cukup — jalankan php laravel_api_resource_json_demo.php di folder proyek. Kalau php artisan serve dari artikel sebelumnya masih hidup, pakai terminal kedua untuk demo PHP dan perintah curl.exe saat menguji bentuk JSON dari rute Laravel. 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 kelas JsonResource di Laravel, pemula sering bingung: field mana yang perlu dikirim? Maka kita mulai dari array PHP biasa supaya perbedaan mentah vs rapi terlihat jelas sebelum dibungkus toArray.

<?php
// Mini: kirim catatan pinjam mentah vs rapi.
$peminjamanMentah = [
    "id" => 10,
    "anggota_id" => 1,
    "judul_buku" => "Dasar PHP",
    "nama_anggota" => "Budi",
    "status" => "aktif",
    "created_at" => "2026-07-20 10:00:00",
];

$peminjamanRapi = [
    "id" => $peminjamanMentah["id"],
    "judul_buku" => $peminjamanMentah["judul_buku"],
    "nama_anggota" => $peminjamanMentah["nama_anggota"],
    "status" => $peminjamanMentah["status"],
    "status_label" => $peminjamanMentah["status"] === "aktif" ? "Sedang dipinjam" : "Sudah kembali",
];

echo json_encode(["mentah" => $peminjamanMentah, "rapi" => $peminjamanRapi], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT), PHP_EOL;

Awam — cara menguji bagian ini: salin potongan di atas ke file misalnya mentah-vs-rapi.php, lalu di terminal Laragon/XAMPP jalankan php mentah-vs-rapi.php. Kalau muncul dua objek JSON (mentah vs rapi) dan yang rapi tanpa anggota_id, ide “sembunyikan yang tidak perlu” sudah terlihat. Versi rapi menambah status_label supaya status lebih manusiawi daripada kode aktif saja.

Alur rapikan — array PHP dulu

Gerakan yang benar selalu sama:

  1. Ambil data mentah — dari basis data atau array contoh.
  2. Rapikan satu baris — pilih field, tambah status_label, sembunyikan anggota_id.
  3. Terapkan ke daftar — fungsi yang sama dipakai ke setiap baris sebelum json_encode.
  4. Kirim JSON — pemanggil membaca slip yang konsisten.
<?php
// Salin ke file misalnya rapikan-cek.php lalu jalankan: php rapikan-cek.php
$peminjaman = [
    ["id" => 10, "anggota_id" => 1, "judul_buku" => "Dasar PHP", "nama_anggota" => "Budi", "status" => "aktif"],
    ["id" => 11, "anggota_id" => 2, "judul_buku" => "Belajar Laravel", "nama_anggota" => "Siti", "status" => "kembali"],
];

function rapikanPeminjaman(array $row): array
{
    return [
        "id" => $row["id"],
        "judul_buku" => $row["judul_buku"],
        "nama_anggota" => $row["nama_anggota"],
        "status" => $row["status"],
        "status_label" => $row["status"] === "aktif" ? "Sedang dipinjam" : "Sudah kembali",
    ];
}

$hasil = array_map("rapikanPeminjaman", $peminjaman);
echo json_encode(["data" => $hasil], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT), PHP_EOL;

Awam — cara menguji bagian ini: salin potongan di atas ke rapikan-cek.php, lalu di terminal jalankan php rapikan-cek.php. Kalau JSON muncul tanpa anggota_id dan ada status_label, rapikan sudah sehat. Bandingkan dengan baris mentah — field internal harus hilang.

Baca pinjam -> Rapikan bentuk -> Resource -> JSON ke pemanggil Baris DB catatan acak Rapikan pilih field Resource toArray JSON slip rapi Slip rapi = field konsisten, status_label manusiawi, tanpa anggota_id mentah. Setelah izin jelas di Policy, kita merapikan apa yang pemanggil baca.
Setelah aturan izin di Authorization Policy: Siapa Boleh Ubah (#66), #67 (ini) merapikan bentuk jawaban JSON lewat Resource.

Laravel — cuplikan JsonResource & toArray (bukan file mandiri)

Di proyek Laravel, bentuk jawaban ditulis di kelas Resource, lalu dipanggil dari pengatur kode sebelum dikirim ke pemanggil.

<?php
// Cuplikan Laravel (bukan file mandiri)
// app/Http/Resources/PeminjamanResource.php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class PeminjamanResource extends JsonResource
{
    public function toArray($request): array
    {
        return [
            "id" => $this->id,
            "judul_buku" => $this->buku->judul,
            "nama_anggota" => $this->anggota->nama,
            "status" => $this->status,
            "status_label" => $this->status === "aktif" ? "Sedang dipinjam" : "Sudah kembali",
        ];
    }
}
<?php
// Cuplikan Laravel (bukan file mandiri)
// app/Http/Controllers/PeminjamanController.php

use App\Http\Resources\PeminjamanResource;
use App\Models\Peminjaman;

public function show(Peminjaman $peminjaman)
{
    return new PeminjamanResource($peminjaman);
}

public function index()
{
    return PeminjamanResource::collection(Peminjaman::paginate(10));
}

Awam: PeminjamanResource::toArray = aturan “field apa saja yang dikirim” — anggota_id sengaja tidak ada. new PeminjamanResource($peminjaman) = bungkus satu baris jadi slip rapi. ::collection = bungkus banyak baris sekaligus — cocok dengan daftar panjang. Cuplikan ini bukan file mandiri — tempel ke proyek kalau rute pinjam sudah ada.

Kalau php artisan serve sudah jalan di terminal pertama, uji bentuk JSON di terminal kedua. Di Windows ketik curl.exe (bukan alias curl saja) supaya PowerShell tidak bingung:

curl.exe "http://127.0.0.1:8000/api/peminjaman/10"
curl.exe "http://127.0.0.1:8000/api/peminjaman"

Awam: respons JSON dari curl.exe adalah cara cepat melihat apakah field konsisten — ada status_label, tidak ada anggota_id mentah. Kalau muncul 404, rute pinjam mungkin belum dipasang — itu wajar; fokus dulu ke demo PHP di atas. Kalau bentuk beda-beda tiap halaman, rapikan belum terpusat di satu Resource.

Pola Dasar — bentuk jawaban JSON yang rapi

  1. 1
    Ambil data mentah
    Dari basis data atau array — fondasi dari langkah sebelumnya.
  2. 2
    Pilih field yang perlu
    Sembunyikan kolom internal — hide anggota_id dari JSON publik.
  3. 3
    Tambah label manusiawi
    status_label lebih awam daripada kode aktif saja.
  4. 4
    Satu fungsi rapikan
    PHP rapikanPeminjaman dulu — jangan copy-paste di banyak tempat.
  5. 5
    Pindah ke Resource
    Tulis toArray di PeminjamanResource; panggil dari pengatur kode.
  6. 6
    Uji bentuk konsisten
    Satu baris · banyak baris · field tersembunyi benar-benar hilang — pakai curl.exe kalau perlu.

Kode lengkap — demo mandiri

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

<?php
declare(strict_types=1);

$peminjaman = [
    ["id" => 10, "anggota_id" => 1, "judul_buku" => "Dasar PHP", "nama_anggota" => "Budi", "status" => "aktif"],
    ["id" => 11, "anggota_id" => 2, "judul_buku" => "Belajar Laravel", "nama_anggota" => "Siti", "status" => "kembali"],
];

function rapikanPeminjaman(array $row): array
{
    return [
        "id" => $row["id"],
        "judul_buku" => $row["judul_buku"],
        "nama_anggota" => $row["nama_anggota"],
        "status" => $row["status"],
        "status_label" => $row["status"] === "aktif" ? "Sedang dipinjam" : "Sudah kembali",
    ];
}

function demo(string $judul, callable $aksi): void
{
    echo "=== {$judul} ===", PHP_EOL;
    $hasil = $aksi();
    echo json_encode($hasil, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT), PHP_EOL, PHP_EOL;
}

demo("Satu baris rapi", function () use ($peminjaman) {
    return rapikanPeminjaman($peminjaman[0]);
});

demo("Daftar rapi", function () use ($peminjaman) {
    return ["data" => array_map("rapikanPeminjaman", $peminjaman)];
});

demo("Tanpa anggota_id", function () use ($peminjaman) {
    $rapi = rapikanPeminjaman($peminjaman[0]);
    return ["punya_anggota_id" => array_key_exists("anggota_id", $rapi)];
});

Awam: tiga skenario di atas menunjukkan pola yang wajar: satu baris rapi, daftar rapi, dan field internal benar-benar hilang. Fungsi rapikanPeminjaman adalah inti logika; demo(...) hanya membungkus output agar mudah dibaca di terminal.

Kesalahan umum

Gejala Penyebab tipikal Perbaikan awam
JSON beda-beda tiap halaman Copy-paste rapikan di banyak tempat Satu fungsi atau satu PeminjamanResource
Kolom internal bocor ke pemanggil Kirim baris mentah dari basis data Pilih field di toArray — hide anggota_id
Status membingungkan Hanya kode aktif tanpa label Tambah status_label manusiawi
Relasi tidak ikut terbaca Lupa ambil judul_buku dari relasi Muat relasi dulu di model Peminjaman
Field hilang di daftar panjang Rapikan hanya di satu aksi, bukan di collection Pakai PeminjamanResource::collection(...) untuk banyak baris
curl aneh atau error di PowerShell Alias curl di PowerShell bukan curl.exe Ketik curl.exe persis seperti contoh, atau uji lewat browser

Latihan singkat

  1. Ubah demo: tambah field dipinjam_sejak di versi rapi dan pastikan anggota_id tetap tidak ikut.
  2. Jelaskan ke teman: beda slip rapi vs catatan acak — pakai analogi perpustakaan mini.
  3. Tulis satu kalimat: kenapa PeminjamanResource lebih rapi daripada copy-paste rapikanPeminjaman di banyak pengatur kode.

FAQ singkat

Apakah Resource menggantikan aturan izin?
Tidak. Aturan izin dari Authorization Policy: Siapa Boleh Ubah (#66) menjawab “boleh atau tidak”. Resource menjawab “bentuk jawaban seperti apa”.

Haruskah selalu pakai kelas Resource?
Untuk belajar, fungsi PHP rapikanPeminjaman di rapikan-cek.php sudah cukup memahami ide. Di proyek Laravel nyata, Resource membantu merapikan saat field bertambah.

Tool apa yang dibuka dulu?
Explorer untuk memastikan folder proyek benar (Resources + Controllers), satu terminal untuk demo PHP, editor untuk pengatur kode. Kalau serve hidup, terminal kedua untuk curl.exe.

Potongan sintaks diuji di mana?
Langkah tengah (rapikan array) salin ke rapikan-cek.php, lalu jalankan php rapikan-cek.php. Demo lengkap diuji dengan php laravel_api_resource_json_demo.php. Cuplikan Laravel ditempel ke app\Http\Resources\PeminjamanResource.php dan app\Http\Controllers\PeminjamanController.php; kalau rute sudah ada, uji bentuk JSON dengan curl.exe di terminal kedua.

Ke mana setelah ini?
Berikutnya alami: Feature Test API (#68) — uji otomatis bahwa bentuk jawaban JSON tetap benar.

Kesimpulan

Kamu sudah merapikan bentuk jawaban JSON: array PHP dulu dengan fungsi rapikanPeminjaman, lalu pindahkan ke API Resource (PeminjamanResource) dan toArray di Laravel. Pemanggil menerima slip pinjam yang konsisten — field sama, status_label manusiawi, tanpa anggota_id mentah.

Seri 5 progress: langkah #67 (ini) · 4/7 Laravel Lanjutan · prasyarat: Authorization Policy: Siapa Boleh Ubah (#66) LIVE. Berikutnya: Feature Test API (#68).