Property Hooks PHP 8.4: Ganti Getter-Setter Lebih Rapi

Diperbaharui 11 November 2026 8:21 PM
PHP

Property hooks PHP 8.4 adalah cara baru membungkus akses properti: logika baca dan tulis ditempel langsung ke deklarasi properti, bukan lagi di method getNama() dan setNama(). Fitur ini resmi masuk sejak PHP 8.4.0 dirilis 21 November 2024 dan kini jadi bagian normal PHP 8.5. Kalau codebase kamu masih bergaya getter-setter klasik, hooks membuat class lebih pendek tanpa mengubah cara pemanggilan dari luar. Yang penting dipahami: hooks bukan sekadar gula sintaks; ada aturan backed versus virtual, inheritance, dan beberapa jebakan.

Apa Itu Property Hooks PHP 8.4

Property hooks adalah mekanisme untuk mencegat operasi baca (get) dan tulis (set) pada sebuah properti. Hooks hanya tersedia untuk properti non-static, baik yang bertipe maupun yang tidak bertipe. Tujuannya dua: memakai properti secara langsung tanpa method pembungkus, dan membuat properti yang nilainya tidak disimpan sama sekali.

Dari situ muncul dua istilah yang wajib dibedakan:

  • Backed property — properti yang benar-benar menyimpan nilai. Properti tanpa hook otomatis termasuk kategori ini.
  • Virtual property — properti yang punya hook, tapi hook-nya tidak menyentuh properti itu sendiri. Hook di sini berperilaku seperti method, dan objek tidak memakai memori untuk menyimpan nilainya.

Cara membedakannya: kalau hook merujuk $this->namaProperti, berarti backed; kalau hanya membaca properti lain, berarti virtual. Satu catatan penting: property hooks tidak kompatibel dengan properti readonly. Untuk membatasi siapa yang boleh menulis, pakai asymmetric visibility.

Sintaks Dasar: get, set, dan $value

Perubahan paling kelihatan: tanda titik koma. Properti yang punya hook diakhiri blok {}, bukan ;. Di dalamnya boleh ada satu atau dua hook, dan urutan penulisannya tidak berpengaruh.

<?php
class Produk
{
    public string $nama = '' {
        set => trim($value);
    }

    public string $slug {
        get => strtolower(str_replace(' ', '-', $this->nama));
    }
}

$p = new Produk();
$p->nama = '  Kopi Gayo  ';
echo $p->nama; // Kopi Gayo
echo $p->slug; // kopi-gayo

Pada contoh di atas, hook set ditulis sebagai arrow expression. Nilai hasil ekspresi itulah yang disimpan ke backing value, jadi trim() otomatis berlaku setiap kali ada yang menulis ke $nama. Parameter tidak perlu ditulis karena tipenya sama dengan properti; PHP memberi nama $value secara otomatis.

Kalau butuh beberapa baris, ganti arrow dengan blok biasa. Di bentuk blok, hook set bertanggung jawab menulis sendiri ke properti, jadi validasi dan penulisan nilai dilakukan manual di dalam kurung kurawal. Tipe parameter boleh lebih lebar (contravariant) dari tipe properti, misalnya set(string|Stringable $value) untuk properti string; yang tidak boleh adalah tipe yang tidak berhubungan seperti array.

Virtual Property untuk Nilai Turunan

Kasus paling rapi untuk virtual property adalah nilai yang sebenarnya hasil hitungan. Dulu pola ini menuntut method getLuas() plus docblock supaya IDE paham. Sekarang cukup satu hook get, dan properti tetap terlihat seperti data biasa.

<?php
class PersegiPanjang
{
    public function __construct(
        public int $panjang,
        public int $lebar,
    ) {}

    public int $luas {
        get => $this->panjang * $this->lebar;
    }
}

$kotak = new PersegiPanjang(4, 5);
echo $kotak->luas; // 20
$kotak->luas = 30; // Error: tidak ada operasi set

Karena tidak ada hook set, properti $luas hanya bisa dibaca. Upaya menulis ke sana akan melempar error, bukan diam-diam diabaikan. Inilah bedanya dengan __get() ajaib yang bisa menelan kesalahan tanpa jejak.

Bedanya dengan Getter-Setter Klasik

Secara fungsi, hook get/set meniru pasangan method yang selama ini kita tulis manual. Bedanya ada di tiga hal:

  • API tidak berubah saat logika ditambah. Properti yang tadinya polos bisa diberi hook kapan saja, dan kode pemanggil tetap menulis $objek->nama. Ini alasan utama hooks ada: menghindari method “jaga-jaga” yang ditulis karena takut suatu hari butuh validasi.
  • Tidak ada panggilan method yang perlu diingat. Tidak ada lagi campuran getNama(), nama(), atau getName() antar class di satu project.
  • Perilaku bawaan tetap ada. Kalau hanya satu hook yang didefinisikan pada backed property, operasi lain memakai perilaku standar. Menulis hook set saja tidak menghilangkan kemampuan membaca properti.

Risikonya psikologis: karena terlihat seperti properti biasa, orang bisa menaruh operasi mahal di dalam hook. Baca fitur baru PHP 8.5 untuk melihat arah bahasa ini bergerak, lalu tentukan batas wajar antara hook dan method.

Asymmetric Visibility: public private(set)

Hooks mengatur perilaku, sedangkan asymmetric visibility mengatur hak akses. Keduanya diperkenalkan di versi yang sama dan sering dipakai berpasangan. Sintaksnya menaruh modifier kedua untuk operasi tulis, sehingga siapa pun boleh membaca properti tapi hanya kode di dalam class yang boleh menulisnya.

<?php
class Pengguna
{
    public private(set) string $namaDepan;

    public function __construct(string $namaDepan)
    {
        $this->namaDepan = $namaDepan;
    }
}

Aturan yang perlu diingat, visibilitas get tidak boleh lebih sempit daripada visibilitas set. Pola ini lebih tepat daripada readonly ketika nilainya masih boleh berubah, hanya saja perubahan harus lewat method tertentu.

Interface Boleh Mendeklarasikan Properti

Perubahan yang mudah terlewat: interface kini bisa mendeklarasikan properti, lengkap dengan operasi mana yang diwajibkan. Class yang mengimplementasikan boleh memenuhinya dengan properti biasa maupun dengan hook. Contohnya public string $namaLengkap { get; } mewajibkan properti yang bisa dibaca, dan implementasinya sah memakai hook get berisi penggabungan dua field lain.

Interface tidak boleh mendeklarasikan properti tanpa menentukan hook-nya. Jadi public string $nama; di dalam interface adalah kesalahan sintaks; tulis { get; }, { set; }, atau keduanya. Ini memaksa kontraknya eksplisit, meski sedikit lebih panjang. Kalau kamu baru pindah dari gaya PHP 5, bagian dasar halaman dinamis dengan PHP tetap relevan untuk memahami alur request-nya.

Hook di Class Turunan dan Kata Kunci final

Hook diwarisi seperti method, dan tiap hook bisa ditimpa secara terpisah. Class anak boleh menambah hook pada properti yang di parent-nya polos, dengan syarat nilai default harus dideklarasikan ulang. Kalau ingin mengunci perilaku, tandai hook dengan final, misalnya final set => strtolower($value);. Class turunan masih boleh menambah hook get, tapi tidak boleh mengganti set.

Untuk memanggil implementasi parent secara eksplisit, gunakan parent::$username::get() atau parent::$username::set($value). Tanpa sintaks itu, hook parent diabaikan sepenuhnya. Kebiasaan ini berguna ketika class induk nanti ditambah validasi sendiri.

Jebakan yang Sering Kelewat

  • readonly tidak bisa dipasangi hook. Pilih salah satu: readonly untuk nilai yang benar-benar tetap, atau hook plus asymmetric visibility untuk nilai yang boleh berubah terkontrol.
  • Referensi dan elemen array. Menulis $this->daftar['kunci'] = 'nilai' pada properti backed yang punya hook akan melewati hook set. Solusinya hanya kalau properti memakai &get saja. Mengganti seluruh array tetap aman.
  • Serialization tidak seragam. var_dump(), serialize(), dan cast ke array memakai nilai mentah, sedangkan json_encode(), var_export(), dan get_object_vars() membaca lewat hook get. Respons API bisa berbeda dari isi database kalau kamu lupa detail ini.
  • Constructor property promotion. Hook boleh dipasang di properti yang dipromosikan, tapi tipe parameter konstruktor tetap mengikuti tipe properti, bukan tipe yang diterima hook set. Kalau butuh menerima tipe lain dari konstruktor, promosi harus dilepas.
  • Konstanta __PROPERTY__. Di dalam hook tersedia konstanta ini yang berisi nama properti, berguna untuk kode berulang. Ini bukan pengganti $this->nama; memakai nama dinamis membuat properti dianggap virtual.
  • Magic method tetap magic. Hooks hanya berlaku untuk properti yang dideklarasikan. Model Eloquent yang mengandalkan __get()/__set() tidak berubah perilakunya hanya karena kamu menambah hook di class lain.

Hook juga sebaiknya tetap murah. Kalau di dalam get ada query database atau panggilan HTTP, setiap pembacaan properti jadi operasi jaringan yang tak terlihat di kode. Untuk kasus itu, method eksplisit lebih jujur. Pola serupa penting saat menyusun relasi data, seperti di tutorial relationship table di Laravel.

Cara Mencoba di Project Sendiri

Syaratnya satu: PHP 8.4 atau lebih baru. Cek versi runtime, lalu lint file yang diubah supaya kesalahan sintaks ketahuan sebelum masuk CI.

php -v
php -l src/Produk.php
php -r 'require "src/Produk.php"; $p = new Produk(); $p->nama = "  Kopi Gayo  "; echo $p->slug, PHP_EOL;'

Kalau project masih di 8.2 atau 8.3, hooks belum bisa dipakai dan file gagal di-parse. Untuk library yang dipublikasikan, tambahkan syarat versi di composer.json sebelum memakai fitur ini.

FAQ

Apakah property hooks menggantikan getter dan setter sepenuhnya? Tidak. Hooks cocok untuk validasi, normalisasi, dan nilai turunan; method lebih jelas untuk operasi berat atau yang jadi bagian alur bisnis.

Apakah menambah hook mengubah kode pemanggil? Tidak. Akses tetap $objek->properti, dan selama tipe serta nama properti tidak berubah, kode lama tetap jalan.

Bisa dipakai di properti static? Tidak. Hooks hanya untuk properti non-static. Untuk properti static, tetap pakai method atau pola lama.

Kesimpulan

Property hooks membuat class PHP lebih ringkas tanpa mengorbankan kemampuan menambah aturan nanti. Kuncinya tiga keputusan: tentukan backed atau virtual, pilih hook atau asymmetric visibility, lalu jaga isi hook tetap ringan. Kalau itu dipegang, hooks jadi alat yang rapi; kalau dilewati, kompleksitasnya cuma pindah ke tempat yang lebih sulit dilacak.

Referensi

susantokun avatar
susantokun
Hanya seorang programmer yang fokus di bidang web development. Tidak nyaman dengan keramaian dan suka akan keindahan.
Kebijakan Berkomentar :
1. Dilarang berkomentar yang mengandung SPAM, SARA, HOAX, PORNO.2. Mohon sertakan informasi detail saat terjadi error (pesan error, sreenshoot, code, logs, dsb.).