Sepanjang section ini array terbukti serba bisa: menyimpan daftar, memetakan kunci, bahkan meniru stack dan queue. Kelenturan itu punya harga — array tidak punya kontrak: kunci boleh salah tulis, tipe isi boleh campur aduk, dan kesalahan baru terasa jauh setelah data beredar di aplikasi. PHP menyediakan alternatif: stdClass untuk object polos, class dengan typed properties untuk kontrak yang diperiksa runtime, hingga SplFixedArray untuk koleksi hemat memori. Chapter penutup ini bukan tentang fitur baru, melainkan tentang keputusan desain: kapan memakai struktur yang mana.
Tiga Wajah Data yang Sama #
Mari kita letakkan ketiga kandidat berdampingan memuat data produk yang identik. Class di bawah memakai dua fitur yang akan dibahas mendalam di Section Object-Oriented Programming: constructor property promotion (deklarasi properti sekaligus pengisian lewat constructor) dan modifier readonly (nilai tidak bisa diubah setelah dibuat):
<?php
$produkArray = ['id' => 7, 'nama' => 'Mangga', 'harga' => 12000];
$produkObjek = new stdClass();
$produkObjek->id = 7;
$produkObjek->nama = 'Mangga';
$produkObjek->harga = 12000;
class Produk
{
public function __construct(
public readonly int $id,
public readonly string $nama,
public readonly int $harga,
) {}
}
$produk = new Produk(7, 'Mangga', 12000);
echo $produkArray['nama'] . ' / ' . $produkObjek->nama . ' / ' . $produk->nama . "\n";Output yang Dihasilkan:
Mangga / Mangga / ManggaKetiganya sama-sama mudah dibaca titik ini: array memakai kurung siku dan string kunci, stdClass serta class memakai panah dan nama properti tanpa tanda kutip. stdClass adalah class kosong bawaan PHP — object tanpa properti terdefinisi yang bisa diisi apa pun secara dinamis. Perbedaan nyata ketiganya baru muncul saat data dipakai lebih jauh: apa yang terjadi ketika kunci salah tulis, tipe salah isi, atau field ditambah sembarangan.
Class sebagai Kontrak dengan Typed Properties #
Class dengan type declaration pada tiap properti mengubah kesepakatan tak tertulis menjadi kontrak yang diperiksa engine. Membuat Produk dengan id berupa string langsung ditolak:
<?php
class Produk
{
public function __construct(
public readonly int $id,
public readonly string $nama,
public readonly int $harga,
) {}
}
try {
$salah = new Produk('tujuh', 'Mangga', 12000);
echo 'Berhasil dibuat\n';
} catch (TypeError) {
echo "Ditolak: id harus berupa int\n";
}
$salahArray = ['id' => 'tujuh', 'nama' => 'Mangga', 'harga' => 12000];
echo "Array tetap menerima: {$salahArray['id']}\n";Output yang Dihasilkan:
Ditolak: id harus berupa int
Array tetap menerima: tujuhBaris new Produk('tujuh', ...) melempar TypeError yang kita tangkap dengan blok try/catch, sehingga baris Ditolak yang tercetak. Array di sisi lain menerima string 'tujuh' sebagai id tanpa suara — bug semacam ini baru muncul saat perkalian atau perbandingan angka menghasilkan nol. Dengan class, kesalahan tipe tertangkap di lokasi pembuatan data, bukan di ujung aplikasi.
Selain validasi, class bisa membawa perilaku yang menempel pada datanya — sesuatu yang mustahil bagi array dan stdClass:
<?php
class Harga
{
public function __construct(
public readonly int $rupiah,
) {}
public function formatRupiah(): string
{
return 'Rp' . number_format($this->rupiah, 0, ',', '.');
}
}
$total = new Harga(1500000);
echo $total->formatRupiah() . "\n";Output yang Dihasilkan:
Rp1.500.000Method formatRupiah() mengenkapsulasi cara memformat angka khusus rupiah; setiap pemanggil hanya menulis $total->formatRupiah() tanpa menyalin logika number_format ke mana-mana. Pola object ringkas seperti ini — sering disebut value object — juga dipakai sebagai DTO (Data Transfer Object): object sederhana yang hanya mengangkut data antar lapisan aplikasi dengan tipe yang dijamin.
Roundtrip JSON: Bentuk yang Berubah Diam-diam #
JSON adalah tempat array dan object bertukar wajah, dan di sinilah pilihan struktur terasa nyata. Object class di-encode menjadi JSON object dengan properti public-nya:
<?php
class Produk
{
public function __construct(
public readonly int $id,
public readonly string $nama,
public readonly int $harga,
) {}
}
$produk = new Produk(7, 'Mangga', 12000);
$json = json_encode($produk, JSON_UNESCAPED_UNICODE);
echo $json . "\n";
$sebagaiArray = json_decode($json, true);
var_dump($sebagaiArray === ['id' => 7, 'nama' => 'Mangga', 'harga' => 12000]);
$sebagaiObject = json_decode($json);
echo get_class($sebagaiObject) . "\n";Output yang Dihasilkan:
{"id":7,"nama":"Mangga","harga":12000}
bool(true)
stdClassjson_encode($produk) menghasilkan object JSON {"id":7,...} yang sama persis dengan array asosiatif berisi field serupa. Arah baliknya menentukan struktur yang Anda terima: json_decode($json, true) mengembalikan array, sedangkan tanpa true PHP membungkusnya menjadi stdClass. Artinya, data yang berangkat sebagai class bisa kembali sebagai array — dan sebaliknya — sehingga batas antar struktur harus Anda jaga secara sadar di tiap batas sistem.
Bentuk JSON yang dihasilkan juga mengikuti kunci array, bukan niat Anda:
<?php
echo json_encode(['Apel', 'Jeruk']) . "\n";
echo json_encode(['apel' => 3, 'jeruk' => 5]) . "\n";
echo json_encode([1 => 'a', 2 => 'b']) . "\n";Output yang Dihasilkan:
["Apel","Jeruk"]
{"apel":3,"jeruk":5}
{"1":"a","2":"b"}List menjadi array JSON ["Apel","Jeruk"], array asosiatif menjadi object JSON {"apel":3,...}. Yang mengejutkan ada di baris ketiga: kunci numerik yang tidak mulai dari nol juga menjadi object JSON — meskipun terlihat seperti daftar bernomor. Karena itulah fungsi array_is_list() dari Chapter Array Functions
penting: ia satu-satunya cara memastikan array Anda benar-benar akan menjadi array JSON.
Performa dan Memori: Fakta dan Mitos #
Banyak mitos beredar soal “object lebih lambat dari array” atau sebaliknya. Fakta teknisnya lebih membosankan: array asosiatif PHP adalah hash table, dan properti object pun disimpan dalam tabel hash internal, sehingga kecepatan akses keduanya berada di kisaran yang sama. Perbedaan nyata justru pada kejelasan: kontrak tipe class mencegah bug yang mahal, jauh melebihi biaya mikro-benchmark nanodetik.
Untuk memori, memory_get_usage() bisa dipakai untuk mengukur konsumsi aktual di mesin Anda — angkanya bervariasi antar versi PHP dan platform, jadi perlakukan hasilnya sebagai indikatif, bukan kebenaran mutlak. Dua fakta arah yang cukup stabil: array dengan jutaan elemen berindeks numerik lebih hemat memori bila diganti SplFixedArray (lihat Chapter Array Functions
), dan array bersarang dalam yang tidak pernah diubah berbagi memori secara gratis berkat copy-on-write (lihat Chapter Array Copy dan References
).
Tabel Keputusan #
Rangkuman praktis dari seluruh section ini dalam satu tabel:
| Situasi | Struktur yang tepat | Alasan utama |
|---|---|---|
| Data JSON masuk/keluar, bentuk longgar | associative array | roundtrip paling mulus dengan json_decode(..., true) |
| Daftar homogen sederhana (id, baris log) | list array | sederhana, didukung semua fungsi array |
| Kontrak antar lapisan aplikasi (DTO) | class + typed properties | tipe diperiksa runtime, salah tulis field tertangkap |
| Data + perilaku (format, perhitungan) | class (value object) | behavior menempel pada data |
| Konfigurasi banyak opsi | array + defaults ($user + $default) | ringkas dan mudah digabung |
| Koleksi besar, ukuran tetap, memori ketat | SplFixedArray | jejak memori lebih kecil |
| Object polos tanpa kontrak | stdClass | praktisnya hanya untuk hasil json_decode() tanpa true |
Ringkasan #
Array menang di fleksibilitas dan ekosistem fungsi; class menang di kontrak, keamanan tipe, dan enkapsulasi perilaku; stdClass hampir selalu sekadar titik transit dari JSON; SplFixedArray menjawab kebutuhan memori khusus. Keputusan terbaik biasanya bertahap: mulai dari array, lalu naikkan ke class ketika bentuk data stabil dan kesalahan tipe mulai berharga untuk dicegah. Dengan data kini tersusun rapi, kita beralih ke fondasi berikutnya: membungkus logika menjadi unit yang bisa dipakai ulang di Section Fungsi.