# Modul Pembelajaran: PHP Traits & Namespaces

## Bagian 1: Traits

### 1.1. Pengantar
PHP adalah bahasa pemrograman yang mendukung **Single Inheritance**. Artinya, sebuah class hanya dapat mewarisi (extends) dari **satu** class lain. Hal ini bisa menjadi keterbatasan ketika kita ingin menggunakan kembali (reuse) sekumpulan method di beberapa class yang berbeda hierarki.

**Traits** hadir sebagai solusi untuk masalah ini. Traits memungkinkan **Horizontal Code Reuse**, yaitu kemampuan untuk menyisipkan method-method ke dalam class apapun tanpa mempedulikan hierarki inheritance-nya.

### 1.2. Mendefinisikan dan Menggunakan Trait
Trait didefinisikan dengan keyword `trait`. Untuk menggunakannya di dalam class, kita menggunakan keyword `use`.

```php
<?php

trait Logger {
    public function log($msg) {
        echo date('Y-m-d H:i:s') . ": $msg\n";
    }
}

class User {
    use Logger; // Menyisipkan method log() ke class User

    public function create() {
        $this->log("User created");
    }
}

class Product {
    use Logger; // Menyisipkan method log() ke class Product

    public function save() {
        $this->log("Product saved");
    }
}

$user = new User();
$user->create();
```

### 1.3. Precedence (Prioritas)
Jika terjadi konflik nama method antara Trait, Class itu sendiri, dan Parent Class, PHP memiliki aturan prioritas:

1.  **Class saat ini**: Method yang didefinisikan di class itu sendiri memiliki prioritas TERTINGGI.
2.  **Trait**: Method dari Trait akan menimpa method dari Parent Class.
3.  **Parent Class**: Method dari Parent Class memiliki prioritas TERENDAH.

**Contoh:**
```php
class Base {
    public function sayHello() { echo "Hello from Base"; }
}

trait SayWorld {
    public function sayHello() { echo "Hello from Trait"; }
}

class MyClass extends Base {
    use SayWorld;
}

$obj = new MyClass();
$obj->sayHello(); // Output: Hello from Trait
```

### 1.4. Multiple Traits & Conflict Resolution
Sebuah class bisa menggunakan banyak trait sekaligus.
```php
class MyClass {
    use TraitA, TraitB;
}
```

Jika dua trait memiliki method dengan nama yang sama, akan terjadi **Fatal Error**. Kita harus menyelesaikannya dengan operator `insteadof` (memilih salah satu) atau `as` (memberi alias).

**Contoh Konflik:**
```php
trait A {
    public function smallTalk() { echo 'a'; }
    public function bigTalk() { echo 'A'; }
}

trait B {
    public function smallTalk() { echo 'b'; }
    public function bigTalk() { echo 'B'; }
}

class Talker {
    use A, B {
        B::smallTalk insteadof A; // Gunakan smallTalk dari B
        A::bigTalk insteadof B;   // Gunakan bigTalk dari A
        B::bigTalk as talkB;      // Alias bigTalk dari B menjadi talkB
    }
}
```

### 1.5. Fitur Lain pada Traits
-   **Abstract Methods**: Trait bisa memaksa class penggunanya untuk mengimplementasikan method tertentu.
-   **Static Members**: Trait bisa memiliki static properties dan static methods.
-   **Properties**: Trait bisa mendefinisikan properties, tapi class pengguna tidak boleh mendefinisikan property dengan nama yang sama (kecuali visibilitas dan nilai defaultnya sama).

---

## Bagian 2: Namespaces

### 2.1. Pengantar
Seiring membesarnya aplikasi, kemungkinan terjadinya bentrok nama class (Naming Collision) semakin besar. **Namespace** adalah cara untuk mengelompokkan class, interface, function, dan constant ke dalam "ruang nama" tersendiri, mirip dengan struktur folder di sistem operasi.

### 2.2. Mendefinisikan Namespace
Namespace harus dideklarasikan di baris pertama file PHP (setelah `<?php`).

```php
<?php
namespace App\Models;

class User {
    public function __construct() {
        echo "Ini class User di namespace App\Models";
    }
}
```

### 2.3. Menggunakan Namespace (Keyword `use`)
Untuk menggunakan class dari namespace lain, kita bisa memanggil nama lengkapnya (Fully Qualified Name) atau mengimpornya dengan keyword `use`.

**Cara 1: Fully Qualified Name**
```php
$user = new \App\Models\User();
```

**Cara 2: Import dengan `use`**
```php
use App\Models\User;

$user = new User();
```

### 2.4. Aliasing (Keyword `as`)
Jika kita perlu menggunakan dua class dengan nama yang sama dari namespace berbeda, kita bisa menggunakan alias.

```php
use App\Models\User;
use App\ThirdParty\User as ThirdPartyUser;

$myUser = new User();
$otherUser = new ThirdPartyUser();
```

### 2.5. Struktur Folder (PSR-4)
Standar PSR-4 merekomendasikan agar struktur folder mengikuti struktur namespace.
-   Namespace `App\Models` -> Folder `App/Models`
-   Namespace `App\Controllers\Admin` -> Folder `App/Controllers/Admin`

Ini memudahkan fitur **Autoloading** (memuat class secara otomatis tanpa `require` manual) yang biasa digunakan oleh Composer.

### 2.6. Global Namespace
Class bawaan PHP (seperti `Exception`, `DateTime`, `ArrayObject`) berada di Global Namespace. Jika kita sedang berada di dalam sebuah namespace, kita harus menambahkan backslash `\` di depan nama class global tersebut agar PHP mencarinya di root, bukan di namespace saat ini.

```php
namespace App\Services;

class DateService {
    public function getNow() {
        // return new DateTime(); // ERROR: Mencari App\Services\DateTime
        return new \DateTime();   // BENAR: Mencari DateTime global
    }
}
```
