Sejauh ini kita menulis program dengan gaya prosedural: data disimpan di variabel dan array, lalu diolah oleh function yang berdiri sendiri. Cara ini memadai untuk program kecil, tetapi ketika data dan operasinya bertambah, keduanya mudah terpisah — function hitungDiskon() bisa lupa dipakai, dan array produk bisa kehilangan satu kunci tanpa ada yang menyadarinya. Object-oriented programming (OOP) menawarkan cara lain: data dan perilaku yang saling berkaitan dikemas bersama dalam satu unit bernama class. Pada Chapter ini kita akan mempelajari dua fondasi OOP di PHP, yaitu class sebagai cetakan dan object sebagai wujud nyatanya.
Class sebagai Cetakan, Object sebagai Wujud #
Class adalah definisi — sebuah cetakan (blueprint) yang menetapkan data apa saja yang dimiliki sebuah entitas dan operasi apa saja yang bisa dilakukan terhadap data tersebut. Object adalah wujud nyata dari cetakan itu: satu entitas di memori yang benar-benar menyimpan nilai. Satu class bisa dicetak menjadi banyak object, sama seperti satu cetakan kue bisa menghasilkan banyak kue dengan bentuk sama namai isi yang berbeda-beda. Tabel berikut merangkum perbedaan keduanya:
| Aspek | Class | Object |
|---|---|---|
| Wujud | Definisi di dalam kode | Instance nyata di memori |
| Jumlah | Satu definisi | Banyak, saling independen |
| Dibuat dengan | Kata kunci class | Kata kunci new |
| Memuat | Rancangan property dan method | Nilai property yang konkret |
Perlu dicatat batas analogi cetakan kue: class bukan sekadar alat menyalin nilai, melainkan kontrak tentang struktur data dan perilaku yang dimiliki setiap object hasil cetakannya. Kontrak inilah yang membuat program besar tetap teratur karena PHP bisa memastikan setiap object mengikuti bentuk yang sama.
Membuat Object dengan new #
Mari kita mulai dari class sederhana yang memodelkan produk toko online:
<?php
class Produk
{
public string $nama = "Tanpa nama";
public int $harga = 0;
public function tampilkanInfo(): string
{
return "{$this->nama} - Rp{$this->harga}";
}
}
$laptop = new Produk();
$laptop->nama = "Laptop Gaming";
$laptop->harga = 15000000;
echo $laptop->tampilkanInfo() . "\n";Output yang Dihasilkan:
Laptop Gaming - Rp15000000Mari kita telaah baris-baris kode di atas:
- Baris 2 (
class Produk): mendefinisikan class baru bernamaProduk. Definisi ini belum menyimpan data apa pun; class hanya berupa rancangan. - Baris 4-5: mendeklarasikan dua property — variabel yang melekat pada setiap object — masing-masing dengan nilai default. Kata kunci
publicberarti property boleh diakses dari luar class. - Baris 7-10: mendefinisikan method
tampilkanInfo(), yaitu function yang melekat pada class. Method ini mengembalikan string seperti function biasa yang sudah kita kenal pada Section Fungsi. - Baris 13 (
$laptop = new Produk();): operatornewmemerintahkan PHP mencetak object baru dari cetakanProduk, lalu object tersebut disimpan ke variabel$laptop. - Baris 14-15: operator panah (
->) dipakai untuk mengakses anggota object, baik menulis nilai ($laptop->nama = ...) maupun membacanya. - Baris 17: memanggil method
tampilkanInfo()pada object$laptop, lalu hasilnya dicetak denganecho.
Perhatikan baris 9. Di dalam method, variabel $this merujuk pada object yang sedang memanggil method tersebut — dalam kasus ini $laptop. Tulisan {$this->nama} berarti “ambil nilai property $nama milik object yang sedang aktif”. Berkat $this, satu definisi method yang sama bisa melayani semua object hasil cetakan class yang sama.
Property dengan Nilai Default #
Nilai yang ditulis langsung pada deklarasi property menjadi nilai awal setiap object yang baru dicetak. Pada contoh sebelumnya, object $laptop sempat bernilai "Tanpa nama" dan 0 selama sepersekian detik sebelum kita menimpanya. Sebelum PHP 7.4, property harus dideklarasikan tanpa tipe; gaya lama ini masih sering dijumpai pada kode warisan:
<?php
class Pesan
{
public $isi;
}
$pesan = new Pesan();
var_dump($pesan->isi);Output yang Dihasilkan:
NULLProperty $isi tidak memiliki tipe dan tidak diberi nilai default, sehingga PHP diam-diam mengisinya dengan NULL — var_dump() menegaskan hal tersebut. Perilaku senyap seperti ini adalah salah satu alasan property bertipe lebih disukai pada kode modern. Berbeda dengan property tanpa tipe, property bertype yang tidak diberi default akan menolak pembacaan sebelum nilainya diisi; perilaku ini kita bahas tuntas pada Chapter Object Initialization.
Setiap Object Bersifat Independen #
Dua object dari class yang sama tidak berbagi nilai property — masing-masing menyimpan salinan datanya sendiri. Mari kita buktikan dengan sebuah penghitung sederhana:
<?php
class Penghitung
{
public int $jumlah = 0;
public function tambah(): void
{
$this->jumlah = $this->jumlah + 1;
}
}
$a = new Penghitung();
$b = new Penghitung();
$a->tambah();
$a->tambah();
$b->tambah();
echo "Penghitung a: {$a->jumlah}\n";
echo "Penghitung b: {$b->jumlah}\n";Output yang Dihasilkan:
Penghitung a: 2
Penghitung b: 1Pada baris 12-13, dua object dibuat dari cetakan Penghitung yang sama. Pemanggilan $a->tambah() dua kali hanya mengubah property $jumlah milik object $a, sedangkan $b->tambah() hanya mengubah milik $b. Hasilnya a bernilai 2 dan b bernilai 1 — keduanya tidak saling memengaruhi. Inilah makna $this: ketika $a->tambah() berjalan, $this adalah $a; ketika $b->tambah() berjalan, $this adalah $b.
Memeriksa Object dengan instanceof dan get_class #
Saat program membesar, kita sering perlu memastikan sebuah variabel benar-benar berupa object dari class tertentu. Operator instanceof mengembalikan true bila variabel tersebut adalah instance dari class yang dimaksud, dan false bila bukan:
<?php
class Produk
{
}
class Pelanggan
{
}
$barang = new Produk();
var_dump($barang instanceof Produk);
var_dump($barang instanceof Pelanggan);
var_dump(is_object($barang));
echo get_class($barang) . "\n";Output yang Dihasilkan:
bool(true)
bool(false)
bool(true)
ProdukBaris 12 menunjukkan $barang memang instance dari Produk, sedangkan baris 13 mengembalikan false karena $barang bukan instance dari Pelanggan. Function get_class() pada baris 15 mengembalikan nama class dari sebuah object sebagai string, berguna untuk pesan debugging atau pencatatan log. Operator instanceof juga mengenal inheritance — sebuah object Buku dari class yang mewarisi Produk tetap terhitung instance dari Produk; detailnya kita bahas pada Chapter Inheritance.
OOP vs Prosedural dalam Mengatur Kompleksitas #
Untuk merasakan nilai OOP, bandingkan dua potongan program yang melakukan hal yang sama. Versi prosedural menyimpan data dalam array asosiatif dan mengolahnya lewat function terpisah:
<?php
$produk = ["nama" => "Kopi Gayo", "harga" => 85000];
function hitungDiskon(array $produk): int
{
return (int) round($produk["harga"] * 0.1);
}
echo "Diskon {$produk['nama']}: Rp" . hitungDiskon($produk) . "\n";Output yang Dihasilkan:
Diskon Kopi Gayo: Rp8500Versi OOP mengemas data dan operasinya menjadi satu:
<?php
class Produk
{
public string $nama = "Tanpa nama";
public int $harga = 0;
public function hitungDiskon(): int
{
return (int) round($this->harga * 0.1);
}
}
$produk = new Produk();
$produk->nama = "Kopi Gayo";
$produk->harga = 85000;
echo "Diskon {$produk->nama}: Rp" . $produk->hitungDiskon() . "\n";Output yang Dihasilkan:
Diskon Kopi Gayo: Rp8500Kedua versi menghasilkan output yang sama persis, jadi mana yang lebih baik? Pada program sekecil ini, versi prosedural justru lebih pendek dan tetap wajar dipakai. Keunggulan OOP baru terasa ketika kompleksitas bertambah: setiap Produk dijamin punya property $nama dan $harga dengan tipe yang benar, dan setiap operasi terkait produk tinggal dicari di satu tempat. Tabel berikut merangkum perbandingannya:
| Aspek | Gaya prosedural | Gaya OOP |
|---|---|---|
| Penyimpanan data | Array asosiatif lepas dari function | Property di dalam class |
| Operasi data | Function global menerima array sebagai argumen | Method dipanggil lewat object |
| Jaminan bentuk data | Tidak ada — kunci array bisa salah nama | Ada — struktur dipaksa oleh class |
| Skala kecil | Ringkas dan praktis | Bisa terasa berlebihan |
Kita akan kembali membahas keputusan memilih gaya secara jujur pada Chapter Kapan Menggunakan OOP di penghujung Section ini.
Ringkasan #
Class adalah cetakan yang mendefinisikan property (data) dan method (perilaku), sedangkan object adalah wujud cetakan tersebut yang dibuat dengan operator new. Setiap object menyimpan salinan property-nya sendiri sehingga object-object dari class yang sama bersifat independen, dan $this menjadi jembatan bagi method untuk mengakses object yang sedang aktif. Dengan instanceof dan get_class() kita bisa memeriksa identitas sebuah object saat runtime. Setelah memahami wadahnya, saatnya kita isi class dengan property dan method secara lebih lengkap pada Chapter berikutnya.