Sejauh ini property dan method selalu kita akses melalui object: new Pengguna() dulu, baru $pengguna->nama. Padahal tidak semua data dan perilaku membutuhkan wadah object — konversi suhu tidak menyimpan data apa pun, sedangkan jumlah total pelanggan justru harus dibagi oleh semua object agar penghitungannya tidak berantakan. Kata kunci static memindahkan kepemilikan member dari object ke class itu sendiri. Chapter ini membahas cara kerja static property dan method, constant ::class, serta batas tipis antara helper murni yang sehat dan global state yang berbahaya.
Method Static Tanpa Object #
Method static dideklarasikan dengan kata kunci static dan dipanggil langsung dari class memakai operator :: — tanpa new, tanpa object:
<?php
class KonversiSuhu
{
public static function celsiusKeFahrenheit(float $celsius): float
{
return $celsius * 9 / 5 + 32;
}
public static function celsiusKeKelvin(float $celsius): float
{
return $celsius + 273.15;
}
}
echo KonversiSuhu::celsiusKeFahrenheit(100) . "\n";
echo KonversiSuhu::celsiusKeKelvin(25) . "\n";Output yang Dihasilkan:
212
298.15Class KonversiSuhu tidak memiliki property dan tidak perlu menyimpan data; class tersebut sekadar mengelompokkan dua fungsi murni di bawah satu nama. Pemanggilan KonversiSuhu::celsiusKeFahrenheit(100) terbaca seperti fungsi biasa dengan awalan nama class — pola yang sering disebut class sebagai namespace fungsi. Manfaat nyatanya: nama fungsi global tidak menumpuk, pengelompokan terlihat jelas, dan autoloading bekerja otomatis mengikuti lokasi class.
Property Static yang Dibagi Antar Object #
Property static disimpan pada class, bukan pada masing-masing object. Akibatnya, seluruh instance berbagi satu nilai yang sama — perilaku yang pas untuk penghitung bersama:
<?php
class Pelanggan
{
public static int $jumlahTerdaftar = 0;
protected string $nama;
public function __construct(string $nama)
{
$this->nama = $nama;
// Semua object menaikkan nilai property static yang sama.
self::$jumlahTerdaftar++;
}
}
new Pelanggan("Budi");
new Pelanggan("Siti");
new Pelanggan("Dewi");
echo "Jumlah pelanggan: " . Pelanggan::$jumlahTerdaftar . "\n";Output yang Dihasilkan:
Jumlah pelanggan: 3Mari kita telaah mekanismenya:
public static int $jumlahTerdaftar = 0menciptakan satu slot memori milik class, diinisialisasi sekali saat class dimuat.- Setiap
new Pelanggan(...)menjalankan constructor yang menaikkanself::$jumlahTerdaftar— dari dalam class, aksesnya memakaiself::. Pelanggan::$jumlahTerdaftarmembaca nilai akhir dari luar class; tanda$tetap ditulis karena yang dirujuk adalah property, bukan constant.
Tiga object sengaja tidak disimpan ke variabel apa pun, tetapi penghitung tetap mencatat ketiganya karena kenaikan terjadi di dalam constructor. Method biasa juga bebas mengakses member static melalui self:: seperti pada contoh ini — arah aksesnya sah karena konteks object selalu tahu class-nya.
Batasan Konteks Static #
Method static berjalan tanpa object, sehingga variabel $this tidak tersedia di dalamnya. Mencoba mengakses $this dihentikan PHP seketika:
<?php
class Sapa
{
protected string $nama = "Budi";
public static function halo(): string
{
return "Halo, " . $this->nama;
}
}
echo Sapa::halo() . "\n";Output yang Dihasilkan:
Fatal error: Uncaught Error: Using $this when not in object context in /home/z/my-project/php-course/content/php/object-oriented-programming/static-properties-dan-methods/.verify_tmp.php:8
Stack trace:
#0 /home/z/my-project/php-course/content/php/object-oriented-programming/static-properties-dan-methods/.verify_tmp.php(12): Sapa::halo()
#1 {main}
thrown in /home/z/my-project/php-course/content/php/object-oriented-programming/static-properties-dan-methods/.verify_tmp.php on line 8Pesan Using $this when not in object context menegaskan aturannya: tidak ada object, tidak ada $this. Arah sebaliknya justru sah — method biasa boleh mengakses member static melalui self::, seperti constructor Pelanggan pada subbab sebelumnya. Jebakan lain menanti ketika operator -> dipakai pada property static:
<?php
class Counter
{
public static int $hitung = 0;
}
$counter = new Counter();
$counter->hitung = 5;Penugasan $counter->hitung = 5 tidak pernah menyentuh property static. PHP menerbitkan Notice: Accessing static property Counter::$hitung as non static disusul Deprecated: Creation of dynamic property, lalu secara diam-diam membuat property object baru bernama hitung milik $counter — terpisah dari Counter::$hitung yang tetap bernilai 0. Selalu akses property static dengan operator ::, baik dari dalam class (self::) maupun dari luar (NamaClass::).
Constant ::class untuk Nama Class #
PHP menyediakan constant khusus ::class yang dievaluasi menjadi nama class berupa string — tanpa instansiasi dan tanpa memanggil get_class():
<?php
class KontrolerPesan
{
public const ROUTE = "/pesanan";
public static function indeks(): string
{
return "Menampilkan daftar pesanan";
}
}
// ::class menghasilkan nama class sebagai string — tanpa instansiasi.
$namaKelas = KontrolerPesan::class;
var_dump($namaKelas);
var_dump($namaKelas === "KontrolerPesan");
// Pola umum: pemetaan rute → nama class untuk router aplikasi.
$rute = ["/pesanan" => KontrolerPesan::class];
echo $rute["/pesanan"] . "\n";Output yang Dihasilkan:
string(14) "KontrolerPesan"
bool(true)
KontrolerPesanKontrolerPesan::class menghasilkan string "KontrolerPesan" pada contoh tanpa namespace ini. Pola tersebut bersinar pada pemetaan rute: array $rute menautkan URL ke nama class yang kelak bisa diinstansiasi atau diinspeksi oleh router. Pada aplikasi nyata yang memakai namespace, ::class mengembalikan nama lengkap beserta namespacenya — jauh lebih aman daripada mengetik string manual yang rawan salah ketik, karena editor modern dapat melacak referensi ::class secara otomatis.
Kapan Static Tepat Dipakai #
Dua profil penggunaan static sangat berbeda. Profil pertama adalah helper murni tanpa state — seperti Validasi::email() pada chapter sebelumnya atau KonversiSuhu::celsiusKeFahrenheit() di atas — yang selalu mengembalikan hasil sama untuk input sama, mudah diuji, dan tanpa efek samping. Profil kedua adalah property static yang bisa berubah (mutable), yang pada praktiknya adalah variabel global yang menyamar:
<?php
class SesiBelanja
{
public static ?array $keranjang = null;
public static function tambah(string $barang): void
{
self::$keranjang ??= [];
self::$keranjang[] = $barang;
}
}
SesiBelanja::tambah("Buku PHP");
SesiBelanja::tambah("Mouse wireless");
print_r(SesiBelanja::$keranjang);Output yang Dihasilkan:
Array
(
[0] => Buku PHP
[1] => Mouse wireless
)Tampilannya praktis: tanpa object, SesiBelanja::tambah() langsung bekerja. Namun SesiBelanja::$keranjang kini berstatus global — kode mana pun bisa menulisnya, urutan pemanggilan menentukan hasil akhir, dan pengujian otomatis terpaksa membersihkan state di antara test agar hasilnya tidak saling bocor. Ketika class mulai menyimpan data bisnis pada property static mutable, pertimbangkan menyerahkan data tersebut sebagai dependency biasa lewat constructor object.
Ringkasan #
Member static dimiliki oleh class: method static dipanggil lewat NamaClass::method() tanpa object, dan property static dibagi oleh seluruh instance sehingga cocok untuk penghitung atau nilai baca-saja bersama. Di dalam class, self:: menjadi alat akses utama, sementara $this terlarang karena tidak ada konteks object. Constant ::class melengkapi keluarga ini sebagai cara aman mendapatkan nama class dalam bentuk string. Dengan kemampuan menyusun hierarki dan member level class, kita siap menghadapi kebutuhan desain berikutnya: bagaimana memaksa setiap child mengimplementasikan perilaku tertentu? Abstract classes adalah jawabannya.