Magic Method PHP
Kenali method spesial __toString, __get, __set, __call, dan __invoke.
Analogi: Pintu Otomatis
Magic method seperti pintu otomatis mal: kamu tidak menekan tombol "buka", pintu terbuka sendiri saat kamu mendekat. Method bernama __* dipanggil PHP otomatis pada momen tertentu: objek di-echo (__toString), property tak ada diakses (__get), objek dipanggil seperti fungsi (__invoke).
<?php
// Contoh 1: __toString dan __invoke yang paling berguna
class Uang {
public function __construct(private int $rupiah) {}
// Dipanggil otomatis saat objek di-echo atau digabung string
public function __toString(): string {
return "Rp" . number_format($this->rupiah);
}
// Dipanggil saat objek "dipanggil" seperti fungsi: $u()
public function __invoke(int $tambah): self {
return new self($this->rupiah + $tambah);
}
}
$u = new Uang(15000);
echo $u; // "Rp15.000" (tanpa __toString: fatal error!)
$u2 = $u(5000); // __invoke: objek baru Rp20.000
echo $u2;__toString wajib mengembalikan string dan tidak boleh melempar exception (di PHP 8+ boleh, tapi tetap hindari). __invoke membuat objek callable: pola favorit untuk strategi, middleware, dan closure ber-state.
<?php
// Contoh 2: __get/__set/__call untuk akses dinamis terkendali
class Config {
private array $data = [];
public function __set(string $nama, $nilai): void {
// Validasi sebelum simpan: hanya kunci yang dikenal!
$boleh = ["host", "port", "user"];
if (!in_array($nama, $boleh, true)) {
throw new InvalidArgumentException("Kunci $nama tidak dikenal");
}
$this->data[$nama] = $nilai;
}
public function __get(string $nama) {
return $this->data[$nama] ?? null;
}
public function __call(string $nama, array $arg) {
// Method tak ada -> coba sebagai "getXxx()"
if (str_starts_with($nama, "get")) {
$kunci = lcfirst(substr($nama, 3));
return $this->__get($kunci);
}
throw new BadMethodCallException("Method $nama tidak ada");
}
}
$c = new Config();
$c->host = "localhost"; // __set (property private, jadi magic terpanggil)
echo $c->host; // __get: "localhost"
echo $c->getHost(); // __call: "localhost"Poin krusial: magic method hanya terpanggil untuk member yang tidak accessible (private/undefined). $c->host memicu __set karena host bukan property public. Inilah yang memungkinkan "property virtual" dengan validasi.
Jebakan yang Sering Terjadi
Magic method membuat kode tak terduga. IDE tidak bisa autocomplete $c->getHost(), dan pembaca harus tahu ada __call. Aturan: pakai magic method untuk framework/library (ORM, config), hindari di kode aplikasi biasa. Eksplisit selalu menang untuk keterbacaan.
__get tanpa isset/__isset. empty($c->host) dan isset($c->host) tidak memanggil __get, melainkan __isset (yang default-nya false untuk property magic!). Definisikan __isset berpasangan dengan __get agar perilaku konsisten.
Contoh Nyata: ORM Mini
Magic method dipakai framework ORM (seperti Eloquent Laravel) agar $user->nama terasa seperti property padahal datanya dari database:
<?php
class Model {
protected array $atribut = [];
public function __construct(array $atribut = []) {
$this->atribut = $atribut;
}
public function __get(string $nama) {
return $this->atribut[$nama] ?? null;
}
public function __set(string $nama, $nilai): void {
$this->atribut[$nama] = $nilai;
}
}
class User extends Model {}
$u = new User(["nama" => "Sinta", "email" => "[email protected]"]);
echo $u->nama; // "Sinta": __get mengambil dari $atribut
$u->nama = "Budi"; // __set menyimpan ke $atributInilah kenapa di Laravel kamu bisa menulis $user->nama tanpa mendefinisikan property $nama: magic method menjembatani database dan sintaks objek yang elegan.
Catatan teknis: Daftar magic method lengkap:
__construct,__destruct,__call,__callStatic,__get,__set,__isset,__unset,__sleep,__wakeup,__serialize,__unserialize,__toString,__invoke,__set_state,__clone,__debugInfo. Hafalkan yang umum (__toString, __get/__set, __invoke); sisanya cari saat butuh.
Tantangan
Class uang dengan __toString
Buat class Uang dengan property private $rupiah, constructor, dan __toString() yang mengembalikan format "Rp15.000". Pastikan echo new Uang(15000); menampilkan teks tersebut tanpa error.