ให้นึกถึงสถานการณ์: คุณมีฐานข้อมูลขนาดใหญ่ (ประมาณ 10,000 rows หรือเยอะกว่า) และคุณต้องการ update 1 column ของทุกๆตาราง ซึ่งแน่นอนว่าคุณไม่สามารถทำได้ด้วย SQL query เพียงอย่างเดียว คุณต้องอาศัย logic ของ php มาช่วย แต่ทว่า foreach อาจจะทำงานวนลูปจนถึงขีดจัดกัดของการรัน script ของ php (max_execution_time) โดยค่าเริ่มต้นอยู่ที่ 30 วินาที แต่โชคดีที่ Laravel มีวิธีการสำหรับแก้ไขปัญหานี้ :)
ตัวอย่างการเขียนแบบที่อาจจะเกิดปัญหา
$users = User::all();
foreach ($users as $user) {
$some_value = ($user->some_field > 0) ? 1 : 0;
// might be more logic here
$user->update(['some_other_field' => $some_value]);
}
การเขียนลักษณะนี้จะไม่เกิดปัญหา หากข้อมูลไม่เยอะมาก (100 rows หรือ 500 rows) แล้วถ้าคุณมีข้อมูล 10,000 rows 100,0000 rows หรือ 1M rows ล่ะ? ซึ่งมันไม่ได้มีผลเฉพาะกับความเร็วเท่านั้น แต่ยังมีผลต่อการเก็บข้อมูลตารางในตัวแปรของหน่วยความจำสำรอง(RAM) อาจจะส่งผลให้เกิดปัญหา out of memory หรือหน่วยความจำสำรองไม่เพียงพอได้
โดยทาง Laravel มีฟังก์ชั่นสำหรับแก้ไขปัญหาดังกล่าวได้ นั่นคือฟังก์ชั่น chunk() หลักการทำงานคือจะแบ่งข้อมูลทั้งหมดออกเป็นชุดๆ ตามจำนวนที่เรากำหนด ลักษณะเดียวกับ pagination
ตัวอย่างการใช้งาน
User::chunk(100, function ($users) {
foreach ($users as $user) {
$some_value = ($user->some_field > 0) ? 1 : 0;
// might be more logic here
$user->update(['some_other_field' => $some_value]);
}
});
การทำงานของตัวอย่างข้างต้นคือมันจะวนลูป select ข้อมูลมาทีละ 100 rows จากนั้นก็ foreach เพื่อ update พวกมัน และจะทำแบบนี้ไปเรื่อยๆจนครบ ซึ่งจะเห็นว่ามันจะนำเข้าข้อมูลมาทีละชุด ไม่ใช่ข้อมูลทั้งหมดของตาราง ทำให้สามารถทำงานได้ๆสบาย ไม่ต้องกังวลปัญหา speed หรือ out of memory อีกต่อไป^^
Reference