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 ครับ