Menguasai OOP di PHP modern: class, object, visibility public/protected/ private, constructor property promotion, properti readonly, lalu inheritance, interface, abstract class, trait, dan enum — fondasi menuju kode terstruktur dan framework seperti Laravel.

Sampai episode 6 kita menulis kode prosedural. Sejak episode ini, kita masuk paradigma yang menjadi tulang punggung aplikasi PHP modern: Object-Oriented Programming (OOP). Framework seperti Laravel, Symfony, dan WordPress sendiri seluruhnya dibangun di atas konsep ini.
Mengapa OOP penting? Karena aplikasi nyata punya banyak entitas — user, order, product — yang saling berinteraksi. OOP memungkinkan kalian menggabungkan data dan perilaku dalam satu unit (class), membatasi akses agar state tidak rusak dari luar, dan memakai ulang kode lewat inheritance dan interface. Tanpa ini, kode akan cepat jadi kusut saat proyek membesar.
Class adalah cetak biru; object adalah hasil nyatanya:
<?php
declare(strict_types=1);
class User
{
public string $nama;
public int $usia;
public function sapa(): string
{
return "Halo, saya {$this->nama}.";
}
}
$user = new User();
$user->nama = "Devvnull";
$user->usia = 25;
echo $user->sapa(), "\n"; // Halo, saya Devvnull.$this-> mengakses properti/metode dari dalam class. Perhatikan properti diberi tipe (public string $nama) — properti bertipe sudah ada sejak PHP 7.4.
public, protected, privateVisibility mengatur siapa yang boleh mengakses properti/metode:
| Keyword | Akses dari luar class | Akses dari subclass |
|---|---|---|
public | Ya | Ya |
protected | Tidak | Ya |
private | Tidak | Tidak |
Aturan praktis: default ke private, naikkan ke protected bila subclass butuh, dan public hanya untuk API yang benar-benar publik. Membuka semua properti membuat state mudah rusak dari luar.
class Akun
{
public function __construct(
private float $saldo = 0
) {}
public function saldo(): float
{
return $this->saldo;
}
}PHP 8.0 memperkenalkan constructor promotion — deklarasi properti + assignment langsung di parameter __construct:
class Product
{
public function __construct(
public string $nama,
private float $harga,
public readonly string $sku,
) {}
public function hargaDenganPajak(): float
{
return $this->harga * 1.11;
}
}
$produk = new Product("Laptop", 15000000, "LPT-001");
echo $produk->hargaDenganPajak(), "\n";Kode di atas menghapus belasan baris boilerplate deklarasi properti — pola ini sangat umum di kode PHP modern dan framework.
readonly: Immutability (PHP 8.1+)Properti readonly hanya bisa di-set sekali (biasanya di constructor), tidak bisa diubah setelahnya:
class Config
{
public function __construct(
public readonly string $dbHost,
public readonly string $dbName,
) {}
}
$cfg = new Config("localhost", "app_db");
// $cfg->dbHost = "remote"; // Error: cannot modify readonly propertyImmutability mencegah class berubah diam-diam — sangat berharga untuk DTO (episode 21) dan object yang dibagikan antar komponen. Sejak PHP 8.2, seluruh class bisa ditandai readonly (semua propertinya otomatis readonly).
Class bisa mewarisi class lain dengan extends:
class Pembayaran
{
public function __construct(
protected float $jumlah,
) {}
public function bayar(): string
{
return "Membayar {$this->jumlah}";
}
}
class PembayaranQRIS extends Pembayaran
{
public function bayar(): string
{
return "Scan QRIS untuk " . parent::bayar();
}
}
echo (new PembayaranQRIS(50000))->bayar(), "\n";parent:: memanggil metode class induk. Gunakan inheritance dengan bijak: lebih sering kalian butuh interface daripada inheritance dalam.
interface Notifier
{
public function kirim(string $pesan): void;
}
abstract class NotifierDasar implements Notifier
{
public function prefix(): string
{
return "[INFO]";
}
}
class EmailNotifier extends NotifierDasar
{
public function kirim(string $pesan): void
{
echo $this->prefix() . " email: $pesan\n";
}
}Dependency inversion memakai interface sebagai tipe parameter, sehingga kode tidak terikat implementasi konkret — pola ini menjadi fondasi Dependency Injection (episode 21).
Trait adalah kode yang bisa "ditempelkan" ke beberapa class (PHP belum punya multiple inheritance):
trait Loggable
{
public function log(string $pesan): void
{
echo "[LOG] $pesan\n";
}
}
class UserService
{
use Loggable;
}
(new UserService())->log("User dibuat");Gunakan trait untuk perilaku yang dipakai lintas class tanpa relasi "is-a". Hati-hati konflik nama antar trait.
Enum merepresentasikan himpunan nilai tetap — pengganti kelas berisi konstanta:
enum StatusOrder: string
{
case Baru = "baru";
case Dibayar = "dibayar";
case Dikirim = "dikirim";
case Selesai = "selesai";
public function label(): string
{
return ucfirst($this->value);
}
}
$status = StatusOrder::Dibayar;
echo $status->value, "\n"; // dibayar
echo $status->label(), "\n"; // DibayarEnum bertipe (: string) memudahkan persistensi ke database; enum murni (tanpa tipe) untuk logika internal. Nilai yang tidak valid tidak bisa di-assign — menghilangkan kelas bug "typo string".
Tip
Pola yang paling banyak dipakai di framework PHP: interface untuk kontrak, constructor promotion + readonly untuk DTO, dan enum untuk status domain. Prioritaskan ketiganya saat menulis kode baru — hasilnya ringkas dan mudah ditest.
public readonly lalu kurasi API.private vs protected — protected memperluas permukaan API; gunakan private kecuali memang dibutuhkan subclass.Inti yang harus dibawa pulang:
private sebagai default, public hanya untuk API publik.readonly membuat class ringkas dan aman.Di episode 8 selanjutnya kita merapikan organisasi kode: namespace, errors & exception — namespace dan use, autoloading PSR-4, lalu try/catch/finally, custom exception, dan bagaimana PHP 7+ menyatukan error dan exception lewat ErrorException. Kode kalian akan mulai terasa seperti kode framework sungguhan.