Enum, Readonly & Immutability
Enum (pure & backed), method dan interface pada enum, readonly property, readonly class, dan value object yang tak berubah.
Masalah: "string ajaib"
Tanpa enum, status pesanan biasanya berupa string biasa: 'dibayar', 'dikirim'… Satu salah ketik ('dikirm') lolos tanpa error dan baru ketahuan lewat bug. Enum (PHP 8.1) menyelesaikannya: sekumpulan nilai tetap yang dicek oleh PHP.
Enum murni (pure enum)
enum Arah
{
case Utara;
case Selatan;
}
$a = Arah::Utara;
$a === Arah::Utara; // true
$a->name; // "Utara"
Arah::cases(); // [Arah::Utara, Arah::Selatan]
Backed enum — punya nilai
enum StatusPesanan: string
{
case Menunggu = 'menunggu';
case Dibayar = 'dibayar';
case Dikirim = 'dikirim';
public function label(): string
{
return match ($this) {
self::Menunggu => 'Menunggu pembayaran',
self::Dibayar => 'Sudah dibayar',
self::Dikirim => 'Sedang dikirim',
};
}
public function bisaDibatalkan(): bool
{
return $this === self::Menunggu;
}
}
$s = StatusPesanan::from('dibayar'); // dari database; ValueError jika tidak valid
$t = StatusPesanan::tryFrom('ngawur'); // null jika tidak valid
echo $s->value; // "dibayar"
echo $s->label(); // "Sudah dibayar"
Enum bisa punya method, konstanta, dan mengimplementasikan interface, tetapi tidak punya properti dan tidak bisa di-new. Ia sangat cocok dipadukan dengan match (PHP memeriksa bahwa semua case tertangani). Enum juga bisa dipakai sebagai tipe parameter: function ubah(StatusPesanan $status).
Readonly property (8.1)
class Uang
{
public function __construct(
public readonly int $jumlah,
public readonly string $mata = 'IDR',
) {}
public function tambah(Uang $lain): static
{
return new static($this->jumlah + $lain->jumlah, $this->mata);
}
}
$a = new Uang(1000);
$a->jumlah = 5; // Error: Cannot modify readonly property
Properti readonly hanya boleh diisi sekali, dari dalam class (biasanya constructor). Setelah itu terkunci. Objek yang tidak berubah (immutable) jauh lebih mudah dipahami karena tidak ada yang diam-diam mengubahnya — cocok untuk uang, koordinat, tanggal, DTO.
readonly class (8.2)
readonly class Koordinat
{
public function __construct(
public float $lat,
public float $lng,
) {}
}
Semua properti otomatis readonly. Untuk "mengubah" objek immutable, buat salinan baru (pola with…): return new static(...) dengan nilai yang berbeda.
Value Object & DTO
Value object membungkus nilai bermakna (Uang, Email, NomorTelepon) dan memvalidasinya di constructor, sehingga objek yang ada pasti valid. DTO (data transfer object) membawa data antar lapisan (controller → service) dengan tipe jelas, menggantikan array liar.
Kapan memilih apa?
| Kebutuhan | Pakai |
|---|---|
| Himpunan pilihan tetap (status, peran, jenis) | enum |
| Data yang tak boleh berubah setelah dibuat | readonly / readonly class |
| Nilai dari input bebas pengguna | String + validasi (bukan enum) |