Task Scheduling: สั่งให้ Laravel ทำงานอัตโนมัติตามเวลา

1. 🎯 ชื่อตอน (Title): ตอนที่ 31: Task Scheduling พ่อบ้านอัตโนมัติ สั่งงาน Laravel ให้ตรงเวลาเป๊ะ!
2. 📖 เปิดฉาก (The Hook):
มาครับน้องๆ ลากเก้าอี้มานั่งจิบกาแฟกัน… ลองจินตนาการถึงชีวิตโปรแกรมเมอร์ที่ต้องตั้งนาฬิกาปลุกตื่นมาตอนตี 2 ทุกวัน เพื่อกดปุ่ม “ลบข้อมูลขยะ” หรือ “สรุปยอดขายประจำวัน” ดูสิครับ… แค่คิดก็ขอบตาคล้ำแล้วใช่ไหมฮะ!
ในโลกของเซิร์ฟเวอร์ Linux เรามีเครื่องมือที่ชื่อว่า Cron Job เอาไว้ตั้งเวลาทำงานพวกนี้ครับ แต่ปัญหาคลาสสิกที่ Senior ทุกคนต้องเคยเจอคือ พอโปรเจกต์เริ่มใหญ่ขึ้น เรามี Cron Job เป็นสิบๆ ตัว กระจัดกระจายอยู่บนเซิร์ฟเวอร์ วันดีคืนดีเวลาย้ายเซิร์ฟเวอร์ใหม่ดันลืมก๊อปปี้ Cron มาด้วย ระบบพังพินาศเลยครับ แถมเรายังเอาการตั้งเวลาพวกนี้เก็บลง Git (Version Control) ไม่ได้ด้วย
เพื่อจบปัญหานี้ สถาปนิกของ Laravel ได้มอบพลังอำนาจที่เรียกว่า “Task Scheduling” มาให้เราครับ แนวคิดคือ “เราจะไปเซ็ต Cron ที่ระดับเซิร์ฟเวอร์แค่บรรทัดเดียวพอ เพื่อปลุก Laravel ทุกๆ 1 นาที แล้วให้ Laravel ทำหน้าที่เป็นพ่อบ้านคอยเช็คตารางงานทั้งหมดในโค้ดของเราเอง” วันนี้พี่จะพาไปดูความเท่ของการเขียนตารางงานด้วยโค้ดที่อ่านง่ายเหมือนภาษาคนกันครับ!
3. 🧠 แก่นวิชา (Core Concepts):
ระบบ Scheduler ของ Laravel มีความเปลี่ยนแปลงครั้งใหญ่ที่ทำให้ชีวิตเราง่ายขึ้นมากใน Laravel 11:
- ⚡ ย้ายศูนย์บัญชาการ (The Thinner Skeleton):
ในเวอร์ชันก่อนๆ เราต้องไปเขียนตารางงานไว้ในไฟล์
app/Console/Kernel.phpแต่ใน Laravel 11 ไฟล์นี้ถูกตัดออกไปแล้วครับ! การตั้งเวลาทั้งหมดถูกย้ายมารวมไว้ที่ไฟล์routes/console.phpทำให้โค้ดของเราดูคลีนและเข้าถึงง่ายขึ้นมาก - 🕰️ ไวยากรณ์แห่งกาลเวลา (Expressive Syntax):
Laravel มีเมธอด (Methods) สำหรับกำหนดเวลาที่อ่านง่ายสุดๆ เช่น
->daily()(รันทุกเที่ยงคืน),->hourly()(รันทุกชั่วโมง), หรือ->everyFiveMinutes()(รันทุก 5 นาที) - 🧩 สั่งงานได้หลากหลายรูปแบบ: เราสามารถสั่งรันโค้ดแบบ Closure (ฟังก์ชันด่วนๆ), สั่งรัน Artisan Commands, สั่งรัน Queued Jobs หรือแม้แต่สั่งรัน Shell Scripts ในระดับ OS ก็ทำได้หมดเลยครับ

4. 💻 ร่ายมนต์โค้ด (Show me the Code):
เรามาลองทำภารกิจ “พ่อบ้านทำความสะอาด” กันครับ สมมติว่าระบบของเรามีตาราง temporary_files ที่เก็บข้อมูลขยะไว้ และเราต้องการสั่งให้มัน “ลบข้อมูลที่เก่ากว่า 1 เดือน ทิ้งทุกๆ เที่ยงคืน”
สเต็ปที่ 1: เขียนตารางงานใน routes/console.php
เปิดไฟล์ routes/console.php ขึ้นมา แล้วร่ายมนต์ด้วย Schedule Facade ตามนี้เลยครับ:
<?php
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schedule;
use Illuminate\Support\Carbon;
// สั่งงานด้วย Closure ให้ลบข้อมูลขยะทุกเที่ยงคืน
Schedule::call(function () {
// หาข้อมูลที่เก่ากว่า 1 เดือนแล้วลบทิ้ง
DB::table('temporary_files')
->where('created_at', '<=', Carbon::now()->subMonth())
->delete();
})->daily(); // <- เวทมนตร์มันอยู่ตรงนี้! สั่งให้ทำทุกวันตอน 00:00
// ตัวอย่างเพิ่มเติม: ถ้าอยากส่งอีเมลสรุปยอดตอน 8 โมงเช้าของทุกวันจันทร์
Schedule::command('emails:send-weekly-report')
->weeklyOn(1, '8:00');สเต็ปที่ 2: ปลุกพ่อบ้านบน Production Server (ทำครั้งเดียวจบ)
บนเซิร์ฟเวอร์จริง (เช่น Ubuntu) น้องต้องเปิด Terminal แล้วพิมพ์ crontab -e เพื่อเพิ่มคำสั่งนี้ลงไปแค่บรรทัดเดียวครับ:
# ให้ Linux ปลุก Laravel ทุกๆ 1 นาที แล้ว Laravel จะไปจัดการส่วนที่เหลือเอง!
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1สเต็ปที่ 3: วิธีทดสอบตารางงานตอนกำลัง Dev (Local Environment) ตอนเราเขียนโค้ดอยู่ที่เครื่องตัวเอง เราไม่ต้องไปตั้งค่า Linux Cron หรอกครับ ให้เปิด Terminal แล้วรันคำสั่งนี้ทิ้งไว้เลย:
# คำสั่งนี้จะจำลองตัวเองเป็น Cron วนลูปเช็คตารางงานทุก 1 นาที (เหมาะกับตอน Dev มากๆ)
php artisan schedule:work5. 🛡️ เคล็ดลับจากคัมภีร์ลับ (Under the Hood / Pro-Tips):
ในสเกลงานระดับ Enterprise พี่มีข้อควรระวังและเทคนิคขั้นสูงมาฝากครับ:
- 🚧 กันชนงานซ้อน (Preventing Overlaps):
สมมติว่าน้องมีงานที่ต้องรันทุกๆ 1 นาที แต่งานนั้นดันใช้เวลาประมวลผลไป “3 นาที” สิ่งที่เกิดขึ้นคือ งานเก่าทำไม่เสร็จ งานใหม่ก็พุ่งเข้ามาแทรก (Overlap) ทำให้เซิร์ฟเวอร์ค้างได้! วิธีแก้คือเติม
->withoutOverlapping();ต่อท้ายครับ Laravel จะล็อกงานนี้ไว้จนกว่าจะทำเสร็จ งานรอบใหม่ที่มาถึงก็จะถูกข้ามไปอย่างปลอดภัย - 🌍 วิ่งบนเซิร์ฟเวอร์เดียว (onOneServer):
ถ้าน้องมีเว็บเซิร์ฟเวอร์ 3 เครื่องช่วยกันทำงาน (Load Balancer) Cron Job มันจะรันพร้อมกันทั้ง 3 เครื่อง! (ส่งอีเมลซ้ำ 3 ฉบับ ลูกค้าด่าตายเลย) ให้ใช้คำสั่ง
->onOneServer();ครับ (ต้องใช้งานร่วมกับ Redis หรือ Memcached) เซิร์ฟเวอร์เครื่องแรกที่ชิงงานได้ จะล็อกงานนั้นไว้ไม่ให้เครื่องอื่นแย่งทำ - 👻 โยนไปทำเบื้องหลัง (Background Tasks):
โดยปกติ Scheduler จะทำตามลำดับ ถ้างานแรกใช้เวลา 10 นาที งานที่สองก็ต้องรอนานเลย ถ้าน้องอยากให้มันรันพร้อมๆ กันโดยไม่รอ (Asynchronous) ให้เติม
->runInBackground();เข้าไปครับ (ใช้ได้เฉพาะกับcommandและexecนะครับ) - 🛠️ ห้ามกวนตอนปรับปรุงเว็บ (Maintenance Mode):
จำไว้ว่าตอนน้องรันคำสั่ง
php artisan down(ปิดเว็บซ่อมแซม) Scheduled Tasks จะ หยุดทำงานทั้งหมด โดยอัตโนมัติเพื่อความปลอดภัยครับ แต่ถ้ามีบางงานที่น้องอยากให้รันทะลุเกราะช่วงปิดเว็บได้ ให้เติม->evenInMaintenanceMode();เข้าไปครับ
6. 🏁 บทสรุป (To be continued…):
เห็นความสุดยอดของ Laravel Task Scheduling หรือยังครับน้องๆ? มันช่วยให้ตารางงานอัตโนมัติของเราทั้งหมด “กลายร่างเป็นโค้ด (Infrastructure as Code)” ทำให้เราสามารถนำขึ้น Git ได้ เพื่อนร่วมทีมเปิดมาอ่านก็เข้าใจทันที และปรับเปลี่ยนเวลาได้โดยไม่ต้องไปแตะต้องเซิร์ฟเวอร์เลย
เมื่อเรามีระบบทำงานเบื้องหลังอัตโนมัติแล้ว… ในตอนหน้า พี่จะพาไปงัดข้อกับระบบจัดการข้อมูลขนาดใหญ่ (Big Data) ด้วยเทคนิคที่เรียกว่า “Database Pagination และ Chunking” มาดูกันว่าเราจะดึงข้อมูลเป็นล้านๆ เรคคอร์ดอย่างไรไม่ให้เซิร์ฟเวอร์หน่วยความจำเต็ม… เตรียมตัวให้พร้อม แล้วพบกันครับ!
ต้องการที่ปรึกษาและพัฒนาระบบ Automation ให้กับโรงงานของคุณ? ทีมงาน WP Solution พร้อมให้บริการออกแบบและติดตั้งระบบแบบครบวงจร ดูรายละเอียดบริการของเราได้ที่: www.wpsolution2017.com หรือพูดคุยปรึกษาเบื้องต้นได้ที่ Line: wisit.p