Python

πŸ›οΈ PHP Object-Oriented Programming

Panduan lengkap belajar PHP OOP dari dasar β€” class, object, inheritance, encapsulation, trait, interface, namespace, autoloading, dan quiz interaktif dengan contoh kode praktis

1. Pengenalan OOP

Object-Oriented Programming (OOP) adalah paradigma pemrograman yang mengorganisasi kode ke dalam "objek" yang memiliki properti (data) dan method (perilaku). OOP membantu membuat kode yang lebih terstruktur, reusable, dan mudah dipelihara.

4 Pilar OOP

Pilar Penjelasan Contoh
EncapsulationMenyembunyikan detail internal, hanya expose yang perluPrivate property dengan getter/setter
InheritanceClass anak mewarisi sifat dan perilaku class parentAdmin extends User
PolymorphismSatu interface, banyak implementasiMethod nama() di class berbeda
AbstractionMenyembunyikan kompleksitas, hanya tampilkan yang esensialAbstract class, interface

OOP vs Procedural

Aspek Procedural OOP
StrukturFungsi-fungsi berdiri sendiriClass dan Object
Reusability🟑 Terbatas🟒 Sangat baik (inheritance)
Maintainability🟑 Sulit di skala besar🟒 Terstruktur dan modular
Data SecurityπŸ”΄ Data terbuka🟒 Encapsulation (access control)
Cocok untukSkrip sederhana, otomasiAplikasi besar, framework
Diagram: Konsep OOP
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                  4 PILAR OOP                           β”‚
β”‚                                                       β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”          β”‚
β”‚  β”‚  Encapsulation   β”‚    β”‚   Inheritance    β”‚         β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚    β”‚   Parent         β”‚         β”‚
β”‚  β”‚  β”‚ - private  β”‚   β”‚    β”‚   β”œβ”€β”€ Child1    β”‚         β”‚
β”‚  β”‚  β”‚ + public   β”‚   β”‚    β”‚   └── Child2    β”‚         β”‚
β”‚  β”‚  β”‚ # protectedβ”‚   β”‚    β”‚                  β”‚        β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                  β”‚
β”‚                                                       β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”          β”‚
β”‚  β”‚  Polymorphism    β”‚    β”‚   Abstraction    β”‚         β”‚
β”‚  β”‚  interface Shape β”‚    β”‚   abstract class β”‚         β”‚
β”‚  β”‚  β”œβ”€β”€ Circle      β”‚    β”‚   Animal         β”‚         β”‚
β”‚  β”‚  β”œβ”€β”€ Square      β”‚    β”‚   (harus di-     β”‚         β”‚
β”‚  β”‚  └── Triangle    β”‚    β”‚    implementasi)  β”‚        β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

2. Class dan Object

Class adalah blueprint (cetakan) untuk membuat objek. Object adalah instance (hasil) dari sebuah class.

Membuat Class Dasar

PHP β€” Class Dasar
<?php
// Mendefinisikan class
class Mobil
{
    // Properties (properti/atribut)
    public string $merek;
    public string $model;
    public int $tahun;
    public string $warna;
    private int $kecepatan = 0;

    // Constructor β€” dipanggil saat object dibuat
    public function __construct(string $merek, string $model, int $tahun, string $warna)
    {
        $this->merek = $merek;
        $this->model = $model;
        $this->tahun = $tahun;
        $this->warna = $warna;
    }

    // Methods (perilaku/fungsi)
    public function gas(int $tambah): void
    {
        $this->kecepatan += $tambah;
        echo "{$this->merek} {$this->model}: Kecepatan {$this->kecepatan} km/jam<br>";
    }

    public function rem(int $kurang): void
    {
        $this->kecepatan = max(0, $this->kecepatan - $kurang);
        echo "{$this->merek} {$this->model}: Kecepatan {$this->kecepatan} km/jam<br>";
    }

    public function getKecepatan(): int
    {
        return $this->kecepatan;
    }

    // Magic method __toString
    public function __toString(): string
    {
        return "{$this->merek} {$this->model} ({$this->tahun}) - {$this->warna}";
    }
}

// Membuat object (instance) dari class
$mobil1 = new Mobil("Toyota", "Avanza", 2024, "Putih");
$mobil2 = new Mobil("Honda", "Civic", 2023, "Hitam");

// Mengakses properties dan methods
echo $mobil1 . "<br>";          // Toyota Avanza (2024) - Putih
$mobil1->gas(60);               // Toyota Avanza: Kecepatan 60 km/jam
$mobil1->gas(40);               // Toyota Avanza: Kecepatan 100 km/jam
$mobil1->rem(30);               // Toyota Avanza: Kecepatan 70 km/jam

echo $mobil2 . "<br>";          // Honda Civic (2023) - Hitam
$mobil2->gas(120);              // Honda Civic: Kecepatan 120 km/jam
?>

Constructor Promotion (PHP 8+)

PHP β€” Constructor Promotion
<?php
// PHP 8 Constructor Promotion β€” cara singkat!
class Mahasiswa
{
    public function __construct(
        public readonly string $nama,
        public readonly string $nim,
        public readonly string $jurusan,
        public readonly float $ipk = 0.0,
    ) {}
    // Properties otomatis dibuat dari parameter constructor!
}

$mhs = new Mahasiswa("Andi Wijaya", "2024001", "Teknik Informatika", 3.75);
echo $mhs->nama;     // Andi Wijaya
echo $mhs->jurusan;  // Teknik Informatika

// Readonly β€” property tidak bisa diubah setelah di-set
// $mhs->nama = "Budi";  // Error! Cannot modify readonly property

// Enum (PHP 8.1)
enum StatusPembayaran: string
{
    case Pending = 'pending';
    case Lunas = 'lunas';
    case Dibatalkan = 'dibatalkan';

    public function label(): string
    {
        return match($this) {
            self::Pending => '⏳ Menunggu Pembayaran',
            self::Lunas => 'βœ… Pembayaran Lunas',
            self::Dibatalkan => '❌ Dibatalkan',
        };
    }
}

$status = StatusPembayaran::Lunas;
echo $status->label();   // βœ… Pembayaran Lunas
echo $status->value;     // lunas
?>

3. Inheritance (Pewarisan)

Inheritance memungkinkan class anak (child) mewarisi semua properties dan methods dari class parent (superclass). Ini menghindari duplikasi kode dan membuat struktur yang logis.

PHP β€” Inheritance
<?php
// Parent class
class Kendaraan
{
    public function __construct(
        protected string $merek,
        protected string $model,
        protected int $tahun,
        protected int $kecepatan = 0,
    ) {}

    public function gas(int $tambah): void
    {
        $this->kecepatan += $tambah;
    }

    public function rem(int $kurang): void
    {
        $this->kecepatan = max(0, $this->kecepatan - $kurang);
    }

    public function getInfo(): string
    {
        return "{$this->merek} {$this->model} ({$this->tahun}) - {$this->kecepatan} km/jam";
    }
}

// Child class β€” mewarisi Kendaraan
class Mobil extends Kendaraan
{
    public function __construct(
        string $merek, string $model, int $tahun,
        private int $jumlahPintu = 4,
    ) {
        parent::__construct($merek, $model, $tahun);
    }

    // Override method parent
    public function getInfo(): string
    {
        return parent::getInfo() . " | {$this->jumlahPintu} pintu";
    }

    // Method baru khusus Mobil
    public function klakson(): string
    {
        return "πŸš— {$this->merek} {$this->model}: TIN TIN! πŸ”Š";
    }
}

// Child class lain
class Motor extends Kendaraan
{
    public function __construct(
        string $merek, string $model, int $tahun,
        private string $tipeMotor = "matic",
    ) {
        parent::__construct($merek, $model, $tahun);
    }

    public function getInfo(): string
    {
        return parent::getInfo() . " | tipe {$this->tipeMotor}";
    }

    public function wheelie(): string
    {
        return "🏍️ {$this->merek} {$this->model}: Wheelie! πŸ€™";
    }
}

// Menggunakan inheritance
$mobil = new Mobil("Toyota", "Avanza", 2024, 4);
$mobil->gas(60);
echo $mobil->getInfo() . "<br>";  // Toyota Avanza (2024) - 60 km/jam | 4 pintu
echo $mobil->klakson() . "<br>";  // πŸš— Toyota Avanza: TIN TIN! πŸ”Š

$motor = new Motor("Honda", "Beat", 2024, "matic");
$motor->gas(80);
echo $motor->getInfo() . "<br>";   // Honda Beat (2024) - 80 km/jam | tipe matic
echo $motor->wheelie() . "<br>";   // 🏍️ Honda Beat: Wheelie! πŸ€™

// instanceof β€” cek tipe object
var_dump($mobil instanceof Mobil);       // true
var_dump($mobil instanceof Kendaraan);   // true (karena inheritance)
var_dump($motor instanceof Mobil);       // false
?>

Static Properties dan Methods

PHP β€” Static
<?php
class Pengguna
{
    // Static property β€” dimiliki oleh class, bukan object
    private static int $count = 0;
    private static array $instances = [];

    public function __construct(
        public readonly string $nama,
        public readonly string $email,
    ) {
        self::$count++;
        self::$instances[] = $this;
    }

    // Static method β€” bisa dipanggil tanpa membuat object
    public static function getCount(): int
    {
        return self::$count;
    }

    public static function findByEmail(string $email): ?self
    {
        foreach (self::$instances as $instance) {
            if ($instance->email === $email) {
                return $instance;
            }
        }
        return null;
    }
}

new Pengguna("Andi", "andi@mail.com");
new Pengguna("Budi", "budi@mail.com");
new Pengguna("Citra", "citra@mail.com");

echo Pengguna::getCount() . "<br>";  // 3

$user = Pengguna::findByEmail("budi@mail.com");
echo $user?->nama . "<br>";           // Budi
?>

4. Encapsulation (Enkapsulasi)

Encapsulation adalah menyembunyikan data internal dan hanya mengaksesnya melalui method publik. PHP memiliki 3 level akses: public, protected, dan private.

PHP β€” Access Modifiers
<?php
class RekeningBank
{
    // Private β€” hanya bisa diakses dari dalam class ini
    private string $nomorRekening;
    private float $saldo;

    // Protected β€” bisa diakses dari class ini dan child class
    protected string $tipeRekening;

    // Public β€” bisa diakses dari mana saja
    public string $namaPemilik;

    public function __construct(string $nama, string $nomor, float $saldoAwal)
    {
        $this->namaPemilik = $nama;
        $this->nomorRekening = $nomor;
        $this->saldo = $saldoAwal;
        $this->tipeRekening = "Tabungan";
    }

    // Getter β€” mengambil data private
    public function getSaldo(): float
    {
        return $this->saldo;
    }

    public function getNomorRekening(): string
    {
        // Tampilkan hanya 4 digit terakhir
        return "****" . substr($this->nomorRekening, -4);
    }

    // Setter dengan validasi
    public function setor(float $jumlah): void
    {
        if ($jumlah <= 0) {
            throw new InvalidArgumentException("Jumlah setoran harus positif!");
        }
        $this->saldo += $jumlah;
        echo "βœ… Setor Rp" . number_format($jumlah, 0, ',', '.') .
             " | Saldo: Rp" . number_format($this->saldo, 0, ',', '.') . "<br>";
    }

    public function tarik(float $jumlah): void
    {
        if ($jumlah <= 0) {
            throw new InvalidArgumentException("Jumlah penarikan harus positif!");
        }
        if ($jumlah > $this->saldo) {
            throw new RuntimeException("Saldo tidak cukup!");
        }
        $this->saldo -= $jumlah;
        echo "βœ… Tarik Rp" . number_format($jumlah, 0, ',', '.') .
             " | Saldo: Rp" . number_format($this->saldo, 0, ',', '.') . "<br>";
    }

    // Method untuk info
    public function getInfo(): string
    {
        return "Rekening {$this->getNomorRekening()} a.n. {$this->namaPemilik}" .
               " | Saldo: Rp" . number_format($this->saldo, 0, ',', '.');
    }
}

// Menggunakan encapsulation
$rekening = new RekeningBank("Andi Wijaya", "1234567890", 1000000);

echo $rekening->getInfo() . "<br>";
// Rekening ****7890 a.n. Andi Wijaya | Saldo: Rp1.000.000

$rekening->setor(500000);   // βœ… Setor Rp500.000 | Saldo: Rp1.500.000
$rekening->tarik(200000);   // βœ… Tarik Rp200.000 | Saldo: Rp1.300.000

// $rekening->saldo = 9999999;  // Error! Property private

// Readonly class (PHP 8.2)
readonly class Koordinat
{
    public function __construct(
        public float $latitude,
        public float $longitude,
    ) {}
}

$lokasi = new Koordinat(-6.2088, 106.8456);
echo "Jakarta: {$lokasi->latitude}, {$lokasi->longitude}<br>";
// $lokasi->latitude = 0;  // Error! Readonly
?>

5. Abstraction (Abstraksi)

Abstract class dan abstract method memungkinkan Anda mendefinisikan "kontrak" yang harus diikuti oleh class anak. Abstract class tidak bisa diinstansiasi langsung.

PHP β€” Abstract Class
<?php
// Abstract class β€” tidak bisa dibuat object langsung
abstract class Shape
{
    public function __construct(
        protected string $warna = "hitam"
    ) {}

    // Abstract method β€” HARUS diimplementasi oleh child
    abstract public function hitungLuas(): float;
    abstract public function hitungKeliling(): float;

    // Method biasa β€” bisa digunakan langsung oleh child
    public function getInfo(): string
    {
        return "Warna: {$this->warna} | " .
               "Luas: {$this->hitungLuas()} | " .
               "Keliling: {$this->hitungKeliling()}";
    }
}

class Lingkaran extends Shape
{
    public function __construct(
        private float $jariJari,
        string $warna = "merah",
    ) {
        parent::__construct($warna);
    }

    public function hitungLuas(): float
    {
        return M_PI * $this->jariJari ** 2;
    }

    public function hitungKeliling(): float
    {
        return 2 * M_PI * $this->jariJari;
    }
}

class PersegiPanjang extends Shape
{
    public function __construct(
        private float $panjang,
        private float $lebar,
        string $warna = "biru",
    ) {
        parent::__construct($warna);
    }

    public function hitungLuas(): float
    {
        return $this->panjang * $this->lebar;
    }

    public function hitungKeliling(): float
    {
        return 2 * ($this->panjang + $this->lebar);
    }
}

class Segitiga extends Shape
{
    public function __construct(
        private float $alas,
        private float $tinggi,
        private float $sisiA,
        private float $sisiB,
        string $warna = "hijau",
    ) {
        parent::__construct($warna);
    }

    public function hitungLuas(): float
    {
        return 0.5 * $this->alas * $this->tinggi;
    }

    public function hitungKeliling(): float
    {
        return $this->alas + $this->sisiA + $this->sisiB;
    }
}

// Menggunakan polymorphism
$bentuk = [
    new Lingkaran(7),
    new PersegiPanjang(10, 5),
    new Segitiga(6, 8, 10, 8),
];

foreach ($bentuk as $b) {
    echo get_class($b) . ": " . $b->getInfo() . "<br>";
}
// Lingkaran: Warna: merah | Luas: 153.938... | Keliling: 43.982...
// PersegiPanjang: Warna: biru | Luas: 50 | Keliling: 30
// Segitiga: Warna: hijau | Luas: 24 | Keliling: 24
?>

6. Interface

Interface mendefinisikan kontrak (metode apa saja yang harus ada) tanpa implementasi. Sebuah class bisa mengimplementasi beberapa interface sekaligus.

PHP β€” Interface
<?php
// Interface β€” mendefinisikan "kontrak"
interface Serializable
{
    public function serialize(): string;
    public static function unserialize(string $data): self;
}

interface Loggable
{
    public function toLogString(): string;
    public function getLogLevel(): string;
}

interface Cacheable
{
    public function getCacheKey(): string;
    public function getCacheDuration(): int;
    public function isCacheValid(): bool;
}

// Class bisa implementasi beberapa interface
class User implements Serializable, Loggable, Cacheable
{
    public function __construct(
        public int $id,
        public string $nama,
        public string $email,
    ) {}

    // Implementasi Serializable
    public function serialize(): string
    {
        return json_encode([
            'id' => $this->id,
            'nama' => $this->nama,
            'email' => $this->email,
        ]);
    }

    public static function unserialize(string $data): self
    {
        $arr = json_decode($data, true);
        return new self($arr['id'], $arr['nama'], $arr['email']);
    }

    // Implementasi Loggable
    public function toLogString(): string
    {
        return "[USER] ID:{$this->id} {$this->nama} ({$this->email})";
    }

    public function getLogLevel(): string
    {
        return 'info';
    }

    // Implementasi Cacheable
    public function getCacheKey(): string
    {
        return "user:{$this->id}";
    }

    public function getCacheDuration(): int
    {
        return 3600; // 1 jam
    }

    public function isCacheValid(): bool
    {
        return true;
    }
}

// Type hint dengan interface
function logActivity(Loggable $entity): void
{
    echo "[{$entity->getLogLevel()}] {$entity->toLogString()}<br>";
}

function cacheEntity(Cacheable $entity): void
{
    echo "Caching {$entity->getCacheKey()} selama {$entity->getCacheDuration()}s<br>";
}

$user = new User(1, "Andi", "andi@mail.com");
logActivity($user);   // [info] [USER] ID:1 Andi (andi@mail.com)
cacheEntity($user);   // Caching user:1 selama 3600s

// Mengecek interface
var_dump($user instanceof Loggable);   // true
var_dump($user instanceof Cacheable);  // true
?>

7. Trait

Trait adalah mekanisme untuk menghindari keterbatasan single inheritance di PHP. Trait memungkinkan Anda mengelompokkan kode yang bisa digunakan kembali di beberapa class yang tidak berhubungan.

PHP β€” Trait
<?php
// Trait β€” kumpulan method yang bisa "ditumpuk" ke class manapun
trait HasTimestamps
{
    public ?string $createdAt = null;
    public ?string $updatedAt = null;

    public function touch(): void
    {
        $this->updatedAt = date('Y-m-d H:i:s');
    }

    public function markCreated(): void
    {
        $this->createdAt = date('Y-m-d H:i:s');
        $this->touch();
    }

    public function getAge(): string
    {
        if (!$this->createdAt) return 'Belum disimpan';

        $diff = strtotime('now') - strtotime($this->createdAt);
        $days = floor($diff / 86400);
        return "{$days} hari yang lalu";
    }
}

trait HasSlug
{
    public function generateSlug(string $text): string
    {
        $slug = strtolower(trim($text));
        $slug = preg_replace('/[^a-z0-9-]/', '-', $slug);
        $slug = preg_replace('/-+/', '-', $slug);
        return trim($slug, '-');
    }
}

trait HasSearchable
{
    public function search(array $data, string $keyword): array
    {
        return array_filter($data, function ($item) use ($keyword) {
            return str_contains(strtolower(serialize($item)), strtolower($keyword));
        });
    }
}

// Menggunakan trait di class
class Artikel
{
    use HasTimestamps, HasSlug;  // "menumpuk" trait

    public function __construct(
        public string $judul,
        public string $konten,
        public string $slug = '',
    ) {
        $this->slug = $this->generateSlug($judul);
        $this->markCreated();
    }
}

class Komentar
{
    use HasTimestamps;  // Komentar juga pakai HasTimestamps

    public function __construct(
        public string $nama,
        public string $isi,
    ) {
        $this->markCreated();
    }
}

// Trait beraksi!
$artikel = new Artikel("Belajar PHP OOP", "PHP adalah bahasa yang...");
echo "Slug: {$artikel->slug}<br>";         // belajar-php-oop
echo "Dibuat: {$artikel->createdAt}<br>";   // 2026-06-27 10:30:00
echo "Umur: {$artikel->getAge()}<br>";      // 0 hari yang lalu

$komentar = new Komentar("Andi", "Artikelnya bagus!");
echo "Komentar oleh: {$komentar->nama}<br>";

// Trait conflict resolution
trait A {
    public function hello(): string { return "Hello from A"; }
}
trait B {
    public function hello(): string { return "Hello from B"; }
}

class MyClass
{
    use A, B {
        A::hello insteadof B;      // Pakai A, bukan B
        B::hello as helloFromB;    // B diakses sebagai helloFromB
    }
}

$obj = new MyClass();
echo $obj->hello() . "<br>";        // Hello from A
echo $obj->helloFromB() . "<br>";   // Hello from B
?>

8. Namespace

Namespace digunakan untuk mengorganisasi kode dan menghindari konflik nama class. Ini sangat penting dalam proyek besar yang menggunakan banyak library.

PHP β€” Namespace
<?php
// file: app/Models/User.php
namespace App\Models;

class User
{
    public function __construct(
        public string $nama,
        public string $email,
    ) {}

    public function getFullName(): string
    {
        return $this->nama;
    }
}

// file: app/Services/UserService.php
namespace App\Services;

use App\Models\User;           // Import class dari namespace lain
use App\Repositories\UserRepository as UserRepo;  // Alias

class UserService
{
    public function __construct(
        private UserRepo $userRepo,
    ) {}

    public function createUser(string $nama, string $email): User
    {
        return new User($nama, $email);
    }
}

// file: app/Repositories/UserRepository.php
namespace App\Repositories;

use App\Models\User;

class UserRepository
{
    private array $users = [];

    public function save(User $user): void
    {
        $this->users[] = $user;
    }

    public function findAll(): array
    {
        return $this->users;
    }
}

// ===== Menggunakan namespace =====

// Import
use App\Models\User;
use App\Services\UserService;

// Membuat object dari class di namespace berbeda
$user = new User("Andi", "andi@mail.com");
echo $user->getFullName();  // Andi

// Fully qualified name (tanpa use)
$user2 = new \App\Models\User("Budi", "budi@mail.com");

// Namespace functions dan constants
namespace App\Helpers;

const APP_NAME = "BeebaneLabs";
function formatRupiah(float $angka): string
{
    return "Rp" . number_format($angka, 0, ',', '.');
}

// Menggunakan constants dan functions dari namespace
echo \App\Helpers\APP_NAME;              // BeebaneLabs
echo \App\Helpers\formatRupiah(50000);   // Rp50.000
?>

9. Autoloading (PSR-4)

Autoloading memungkinkan PHP memuat class secara otomatis saat pertama kali digunakan, tanpa perlu require atau include secara manual. PHP menggunakan standar PSR-4 untuk autoloading.

JSON β€” composer.json
{
    "name": "beebanelabs/my-project",
    "description": "Proyek PHP dengan PSR-4 Autoloading",
    "type": "project",
    "require": {
        "php": ">=8.2",
        "monolog/monolog": "^3.0"
    },
    "autoload": {
        "psr-4": {
            "App\\": "app/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Tests\\": "tests/"
        }
    }
}

# Setelah mengubah composer.json, jalankan:
# composer dump-autoload

# Mapping:
# App\Models\User        β†’ app/Models/User.php
# App\Http\Controllers\HomeController β†’ app/Http/Controllers/HomeController.php
# App\Services\AuthService β†’ app/Services/AuthService.php

Contoh Struktur dengan PSR-4

Struktur PSR-4
my-project/
β”œβ”€β”€ app/
β”‚   β”œβ”€β”€ Models/
β”‚   β”‚   β”œβ”€β”€ User.php           ← namespace App\Models
β”‚   β”‚   β”œβ”€β”€ Post.php           ← namespace App\Models
β”‚   β”‚   └── Comment.php        ← namespace App\Models
β”‚   β”œβ”€β”€ Services/
β”‚   β”‚   β”œβ”€β”€ UserService.php    ← namespace App\Services
β”‚   β”‚   └── PostService.php    ← namespace App\Services
β”‚   β”œβ”€β”€ Repositories/
β”‚   β”‚   β”œβ”€β”€ UserRepository.php ← namespace App\Repositories
β”‚   β”‚   └── PostRepository.php ← namespace App\Repositories
β”‚   β”œβ”€β”€ Exceptions/
β”‚   β”‚   └── ValidationException.php ← namespace App\Exceptions
β”‚   └── Helpers/
β”‚       β”œβ”€β”€ StringHelper.php   ← namespace App\Helpers
β”‚       └── DateHelper.php     ← namespace App\Helpers
β”œβ”€β”€ tests/
β”‚   β”œβ”€β”€ Unit/
β”‚   β”‚   └── UserTest.php       ← namespace Tests\Unit
β”‚   └── Feature/
β”‚       └── LoginTest.php      ← namespace Tests\Feature
β”œβ”€β”€ vendor/                    ← Composer dependencies + autoload
β”‚   └── composer/
β”‚       └── autoload.php       ← File autoloading utama
└── composer.json              ← Konfigurasi PSR-4 mapping
PHP β€” Menggunakan Autoloading
<?php
// index.php β€” entry point aplikasi
// Cukup require autoload.php, semua class otomatis dimuat!

require_once __DIR__ . '/vendor/autoload.php';

// Langsung gunakan class dari namespace berbeda
// TANPA perlu require manual di setiap file!
use App\Models\User;
use App\Models\Post;
use App\Services\UserService;
use App\Repositories\UserRepository;

$userRepo = new UserRepository();
$userService = new UserService($userRepo);

$user = $userService->createUser("Andi Wijaya", "andi@mail.com");
echo $user->getFullName();  // Andi Wijaya

$post = new Post("Belajar PHP OOP", "Konten artikel...");
echo $post->title;           // Belajar PHP OOP

// PHP akan otomatis mencari:
// App\Models\User β†’ app/Models/User.php
// App\Services\UserService β†’ app/Services/UserService.php
// App\Repositories\UserRepository β†’ app/Repositories/UserRepository.php
?>
πŸ’‘ Tips

Selalu jalankan composer dump-autoload setelah menambah atau memindahkan file class. Untuk production, gunakan composer install --optimize-autoloader untuk performa yang lebih baik. PSR-4 memastikan nama class dan path file harus konsisten β€” App\Models\User harus berada di app/Models/User.php.

10. Quiz: Uji Pemahamanmu!

Setelah membaca tutorial di atas, jawablah 5 pertanyaan berikut untuk menguji pemahamanmu tentang PHP OOP:

Pertanyaan 1: Apa perbedaan antara abstract class dan interface di PHP?

a) Tidak ada perbedaan, keduanya sama
b) Abstract class bisa punya properties dan method dengan isi, interface hanya kontrak tanpa isi
c) Interface bisa diinstansiasi, abstract class tidak
d) Abstract class tidak bisa punya constructor

Pertanyaan 2: Apa fungsi dari trait di PHP?

a) Menggantikan inheritance
b) Mengelompokkan kode yang bisa digunakan di beberapa class yang tidak berhubungan
c) Membuat class yang tidak bisa dimodifikasi
d) Mengelola database secara otomatis

Pertanyaan 3: Access modifier apa yang membuat property hanya bisa diakses dari class itu sendiri?

a) public
b) protected
c) private
d) internal

Pertanyaan 4: Standar apa yang digunakan PHP untuk autoloading class?

a) PSR-0
b) PSR-4
c) PSR-12
d) JSON Schema

Pertanyaan 5: Berapa banyak interface yang bisa diimplementasi oleh satu class di PHP?

a) Hanya 1
b) Maksimal 3
c) Tak terbatas
d) Tidak bisa mengimplementasi interface
πŸ” Zoom
100%
🎨 Tema