PHP Closures
เมื่อช่วงกลางปีที่แล้วเพิ่งมาสังเกตและสงสัยว่าการเขียน route สวยๆของ Laravel เนี่ยเขาทำกันยังไง
Route::get('/', function () {
return 'Hello World';
});
ก็เลยไปหาอ่านดูจนมาได้รู้จักกับ Closure
Closure หรือเรียกอีกชื่อหนึ่งว่า Anonymous functions คือการประกาศ function ขึ้นมาลอยๆโดยไม่จำเป็นต้องมีชื่อ มีประโยชน์กับงานแนว callback ต่างๆ โดยความสามารถนี้เริ่มมีมาตั้งแต่ PHP 5.3 เช่น
<?php$hello = function($name) {
echo “Hello ”, $name, “\n”;
};$hello(“World”); // Hello World
$hello(“วันหยุด”); // Hello วันหยุด
นอกจากนี้ Closure ยังสามารถ inherit variables จากภาย parent scope เข้าไปใช้งานข้างในได้ด้วยการใช้ “use” โดยค่าของ variable ที่เปลี่ยนแปลงภายใน closure จะไม่ส่งผลกับ variable ที่อยู่ด้านนอก
<?php$base_number = 5;$power_by = function($exponent) use ($base_number) {
$base_number = pow($base_number, $exponent);
return $base_number;
};echo $power_by(2), “\n”; // 25
echo $base_number, “\n”; // 5
ตัวอย่างการใช้งานจริง
เนื่องจากงานที่ทำอยู่ส่วนใหญ่จะเป็นการเขียน worker เพื่อรับส่งงานผ่าน RabbitMQ และจะต้องมีการ process บางอย่างระหว่างทาง โดยเราไม่อยากผูก logic การทำงานซับซ้อนไว้ใน class ใด class หนึ่ง เลยใช้ Closure เพื่อมาประกอบร่างสิ่งต่างๆไว้ด้วยกันใน worker
<?php// สร้างตัวรับงานจาก RabbitMQ
$consumer = new Consumer();// สร้างตัวส่งงานที่ทำเสร็จแล้วส่งกลับไปที่ RabbitMQ
$publisher = new Publisher(); // สร้างตัวทำงานบางอย่างที่เราต้องการ
$processor = new Processor();// สร้างตัวเอาข้อมูลลงฐานข้อมูล
$db = new DB();$callback = function($rabbitmq_message) use ($processor, $db, $publisher) {
$processed_item = $processor->process_item($rabbitmq_message);
$db->save($processed_item);
$publisher->publish($processed_item);
};// สั่งให้ consumer ต่อ queue server ไว้และทำการเรียก callback
// เพื่อทำงานตามที่เรากำหนด เมื่อได้ message จาก queue
$consumer->listen($callback);
ตัวอย่างด้านบนเป็นแค่ code หยาบๆพอให้เห็นภาพ ไว้โอกาสหน้าจะมาแชร์เรื่อง RabbitMQ ครับ