Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> PHP

สร้าง Anonymous Object ใน PHP (Anonymous Classes PHP 7+)

ตั้งแต่ PHP 7.0 สามารถสร้าง Class และ Object แบบไม่มีชื่อ (Anonymous Class) ได้เหมือน Lambda Function

Syntax พื้นฐาน

$object = new class($constructorArgs) extends ParentClass implements Interface {
    // Properties
    public $property = 'value';
    
    // Methods
    public function method() {
        return 'hello';
    }
    
    // Constructor
    public function __construct($arg) {
        // ...
    }
};

ตัวอย่างพื้นฐาน

class Logger {
    public function log($message) {
        echo "[LOG] $message\n";
    }
}

// Anonymous Class extends Logger
$logger = new class extends Logger {
    public function log($message) {
        parent::log(strtoupper($message)); // Override: Uppercase
    }
};

$logger->log('hello world'); // [LOG] HELLO WORLD

// ตรวจสอบ Instance
var_dump($logger instanceof Logger); // bool(true)

Use Cases จริง

1. Test Doubles / Mocks (Unit Testing)

interface PaymentGateway {
    public function charge(int $amount): bool;
}

// ใน Test: สร้าง Fake Implementation ทันที
$gateway = new class implements PaymentGateway {
    public bool $charged = false;
    public int $lastAmount = 0;
    
    public function charge(int $amount): bool {
        $this->charged = true;
        $this->lastAmount = $amount;
        return true; // Always succeed in test
    }
};

$service = new PaymentService($gateway);
$service->processPayment(1000);

$this->assertTrue($gateway->charged);
$this->assertEquals(1000, $gateway->lastAmount);

2. One-off Implementation (Callback, Event Handler)

$button->onClick(new class implements ClickHandler {
    public function handle(ClickEvent $event): void {
        // Logic เฉพาะปุ่มนี้
        Analytics::track('button_click', ['id' => $event->buttonId]);
        Notification::send('Button clicked!');
    }
});

3. Factory / Builder Pattern

class ReportBuilder {
    public function build(callable $customizer = null): Report {
        $report = new Report();
        
        if ($customizer) {
            // ให้ Anonymous Class ปรับแต่ง Report
            $customizer($report);
        }
        
        return $report;
    }
}

// ใช้งาน
$report = (new ReportBuilder())->build(function(Report $r) {
    $r->setTitle('Monthly Sales');
    $r->addChart(new class implements Chart {
        public function render(): string { return '
Chart
'; } }); });

4. Dependency Injection Container (Simple)

$container = new class {
    private $services = [];
    
    public function set(string $id, callable $factory) {
        $this->services[$id] = $factory;
    }
    
    public function get(string $id) {
        if (!isset($this->services[$id])) {
            throw new Exception("Service $id not found");
        }
        return ($this->services[$id])($this);
    }
};

$container->set('db', fn($c) => new PDO('sqlite::memory:'));
$container->set('repo', fn($c) => new UserRepository($c->get('db')));

เข้าถึง Variable ภายนอก (Closure-like)

$prefix = '[DEBUG] ';

$logger = new class($prefix) {
    private $prefix;
    
    public function __construct($prefix) {
        $this->prefix = $prefix;
    }
    
    public function log($msg) {
        echo $this->prefix . $msg . "\n";
    }
};

$logger->log('Test'); // [DEBUG] Test

⚠️ ข้อจำกัด

  • ไม่สามารถ Serialize ได้ (PHP 7.4+ เริ่มรองรับบางกรณี)
  • ไม่สามารถ Type Hint ได้โดยตรง (ใช้ Interface แทน)
  • แต่ละ new class สร้าง Class ใหม่ทุกครั้ง (Memory/Performance)
  • ไม่สามารถ Extends Anonymous Class อื่นได้

ตัวอย่างจากคำถามเดิม (ปรับปรุง)

greet(); // Hello from anonymous child