PHP Traits & Namespaces

Horizontal Code Reuse & Struktur Kode yang Rapi

Oleh: Ahmad Muyassar, S.Kom.,M.Cs

Agenda Pembelajaran

Masalah pada Single Inheritance

PHP hanya mendukung Single Inheritance. Sebuah class hanya bisa extends satu parent class.

Bagaimana jika kita ingin menggunakan method yang sama di beberapa class yang tidak saling berhubungan?


class A {
    public function log() { ... }
}

class B extends A { ... }

// Class C butuh method log() juga,
// tapi sudah extends class lain.
class C extends OtherClass {
    // Error: Cannot extend A too
}
                    

Solusi: Traits

Traits adalah mekanisme untuk code reuse (penggunaan kembali kode) pada bahasa yang mendukung single inheritance seperti PHP.

Traits memungkinkan developer untuk me-reuse method-method dalam beberapa class yang independen.

Mendefinisikan Trait

Gunakan keyword trait diikuti dengan nama trait.


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

Menggunakan Trait

Gunakan keyword use di dalam class untuk memasukkan trait.


class User {
    use Logger;

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

$user = new User();
$user->create(); // Output: 2023-10-27 10:00:00: User created
            

Horizontal Code Reuse

Trait Logger
Class User
Class Product

Berbeda dengan Inheritance (Vertikal), Traits bekerja secara Horizontal. Class User dan Product tidak perlu memiliki hubungan parent-child.

Multiple Traits

Sebuah class bisa menggunakan lebih dari satu trait.


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

trait World {
    public function sayWorld() { echo "World"; }
}

class MyWorld {
    use Hello, World;
}
            

Trait di dalam Trait

Trait juga bisa menggunakan trait lain.


trait HelloWorld {
    use Hello, World;
}

class MyClass {
    use HelloWorld;
}
            

Precedence (Prioritas)

Urutan prioritas method jika ada nama yang sama:

  1. Method di Class itu sendiri (Tertinggi)
  2. Method dari Trait
  3. Method dari Parent Class (Terendah)

Contoh Precedence


class Base {
    public function say() { echo "Base"; }
}

trait SayTrait {
    public function say() { echo "Trait"; }
}

class Child extends Base {
    use SayTrait;
}

$obj = new Child();
$obj->say(); // Output: Trait
            

Konflik Nama Method

Jika dua trait memiliki method dengan nama yang sama, akan terjadi Fatal Error.


trait A { function smallTalk() { echo 'a'; } }
trait B { function smallTalk() { echo 'b'; } }

class Talker {
    use A, B; // Fatal Error: Collision
}
            

Solusi Konflik: insteadof

Gunakan operator insteadof untuk memilih salah satu.


class Talker {
    use A, B {
        A::smallTalk insteadof B;
    }
}
            

Solusi Konflik: as

Gunakan operator as untuk memberi alias pada method yang konflik.


class Talker {
    use A, B {
        B::smallTalk as talkB;
    }
}
            

Namespaces

Mengorganisir Kode Anda

Apa itu Namespace?

Namespace adalah cara untuk mengelompokkan class, interface, function, dan constant yang saling berhubungan.

Analogi: Seperti folder di sistem operasi. File home.txt di folder A berbeda dengan home.txt di folder B.

Masalah Tanpa Namespace

Nama class harus unik secara global. Ini sulit jika menggunakan library pihak ketiga.


// Library A
class User { ... }

// Library B
class User { ... }

// Error: Cannot redeclare class User
            

Mendefinisikan Namespace

Deklarasikan namespace di baris paling atas file PHP.


namespace App\Models;

class User {
    public function __construct() {
        echo "User dari App\\Models";
    }
}
            

Struktur Folder & Namespace

Standar PSR-4 merekomendasikan struktur folder mengikuti namespace.

  • 📂 App
    • 📂 Models
      • 📄 User.php // namespace App\Models;
    • 📂 Controllers
      • 📄 UserController.php // namespace App\Controllers;

Mengakses Class

Untuk menggunakan class dari namespace lain, kita bisa menggunakan Fully Qualified Name.


$user = new \App\Models\User();
            

Atau menggunakan keyword use.

Keyword use

Keyword use digunakan untuk mengimpor class/namespace agar tidak perlu menulis nama lengkapnya berulang kali.


namespace App\Controllers;

use App\Models\User;

class UserController {
    public function index() {
        $user = new User(); // Tidak perlu \App\Models\User
    }
}
            

Alias dengan as

Jika ada nama class yang sama dari namespace berbeda, gunakan as.


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

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

Group Use Declarations

Sejak PHP 7, kita bisa mengelompokkan use statement dari namespace yang sama.


// Sebelum
use App\Models\User;
use App\Models\Product;

// Sesudah
use App\Models\{User, Product};
            

Global Namespace

Class bawaan PHP (seperti Exception, DateTime) berada di global namespace.

Jika kita berada dalam sebuah namespace, akses class global dengan backslash \ di depannya.


namespace App;

function test() {
    throw new \Exception("Error!");
}
            

Kesimpulan

Terima Kasih

Ada Pertanyaan?

1 / 26