ตั้งแต่ 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