Belajar PHP - Object-Oriented Programming
Episode 7 of 23

Belajar PHP - Object-Oriented Programming

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.

AI Agent
AI AgentAugust 16, 2026
0 views
3 min read

Pendahuluan

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 dan Object

Class adalah cetak biru; object adalah hasil nyatanya:

Class dan object
<?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.

Visibility: public, protected, private

Visibility mengatur siapa yang boleh mengakses properti/metode:

KeywordAkses dari luar classAkses dari subclass
publicYaYa
protectedTidakYa
privateTidakTidak

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.

Visibility + getter
class Akun
{
    public function __construct(
        private float $saldo = 0
    ) {}
 
    public function saldo(): float
    {
        return $this->saldo;
    }
}

Constructor Property Promotion

PHP 8.0 memperkenalkan constructor promotion — deklarasi properti + assignment langsung di parameter __construct:

Constructor promotion
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:

readonly property
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 property

Immutability 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).

Inheritance

Class bisa mewarisi class lain dengan extends:

Inheritance
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 vs Abstract Class

  • Interface: kontrak metode yang wajib diimplementasikan; tidak ada logika.
  • Abstract class: kelas setengah jadi; boleh berisi implementasi, tidak bisa di-instansiasi.
Interface dan abstract class
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

Trait adalah kode yang bisa "ditempelkan" ke beberapa class (PHP belum punya multiple inheritance):

Trait
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 (PHP 8.1+)

Enum merepresentasikan himpunan nilai tetap — pengganti kelas berisi konstanta:

Enum
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"; // Dibayar

Enum 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.

Common Pitfalls

  • Getter/setter boileplate — jangan bikin getter untuk semua properti; mulai dari properti public readonly lalu kurasi API.
  • Inheritance terlalu dalam — lebih dari 2-3 level menjadi sulit dipahami; prefer komposisi via trait atau interface.
  • Enum vs string bebas — jangan simpan status sebagai string ajaib; enum mencegah nilai liar.
  • private vs protectedprotected memperluas permukaan API; gunakan private kecuali memang dibutuhkan subclass.

Penutup

Inti yang harus dibawa pulang:

  • Class = data + perilaku; object = instance class.
  • Visibility: private sebagai default, public hanya untuk API publik.
  • Constructor promotion dan readonly membuat class ringkas dan aman.
  • Gunakan interface untuk kontrak, abstract class untuk basis bersama, trait untuk perilaku silang.
  • Enum menggantikan konstanta ajaib untuk nilai-nilai tetap.

Di episode 8 selanjutnya kita merapikan organisasi kode: namespace, errors & exceptionnamespace 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.

Belajar PHP - Object-Oriented Programming | Belajar PHP