Error Handling & Logging: รับมือกับบั๊กและการเก็บ Log

1. 🎯 ชื่อตอน (Title): ตอนที่ 33: Error Handling & Logging กล่องดำนักสืบ และศิลปะการซ่อนบั๊กไม่ให้ลูกค้าตกใจ
2. 📖 เปิดฉาก (The Hook):
มาครับน้องๆ ลากเก้าอี้มานั่งจิบกาแฟกัน… เคยไหมครับ? ตอนเขียนโค้ดอยู่ที่เครื่องตัวเอง (Local) ทุกอย่างทำงานได้สมบูรณ์แบบไร้ที่ติ แต่พอเอาขึ้นเซิร์ฟเวอร์จริง (Production) ปุ๊บ ลูกค้าโทรมาด่าว่า “น้อง! เว็บพัง กดจ่ายเงินไม่ได้ หน้าจอขาวจั๊วะเลย!”
พอเราเข้าไปดูก็พบกับความสยองขวัญ 2 เด้ง: เด้งที่ 1: หน้าเว็บแสดง Error Stack Trace ยาวเป็นหางว่าว โชว์ให้ลูกค้าเห็นหมดเลยว่าเราใช้ Database รหัสผ่านอะไร โฟลเดอร์อยู่ที่ไหน (นี่มันช่องโหว่ความปลอดภัยชัดๆ!) เด้งที่ 2: พอเราปิดการแสดง Error ปุ๊บ ลูกค้าเห็นแค่คำว่า “500 Server Error” แต่คราวนี้ตัวเราเองกลับตาบอด ไม่รู้เลยว่าบั๊กมันเกิดที่บรรทัดไหน เพราะไม่ได้จดบันทึกอะไรไว้เลย!
การปล่อยระบบขึ้น Production โดยไม่มีระบบจัดการ Error และไม่มีการเก็บ Log ก็เหมือนกับการ “ขับรถหลับตา” ครับ วันนี้พี่จะพาไปดูวิธีรับมือกับสถานการณ์ฉุกเฉินเหล่านี้ ทั้งการสร้างหน้าต่าง Error สวยๆ ปลอบใจลูกค้า และการฝัง “กล่องดำ (Black Box)” เพื่อบันทึกทุกฝีก้าวของระบบกันครับ!
3. 🧠 แก่นวิชา (Core Concepts):
สถาปัตยกรรมของ Laravel เตรียมเครื่องมือสำหรับจัดการเรื่องปวดหัวเหล่านี้ไว้ให้อย่างครบครันครับ:
- 🚦 สวิตช์พระเจ้า (The
APP_DEBUGSwitch): ในไฟล์.envจะมีตัวแปรที่ชื่อว่าAPP_DEBUGกฎเหล็กข้อแรกของวงการคือ “บน Production ค่านี้ต้องเป็น false เสมอ” หากเป็นfalseเวลาระบบพัง มันจะไม่คายความลับออกมา แต่จะโชว์หน้าจอ Error พื้นฐานแทน - 🎨 Custom HTTP Error Pages:
HTTP Status Codes ยอดฮิตอย่าง
404 (Not Found)หรือ500 (Internal Server Error)มีหน้าตาเริ่มต้นที่ดูจืดชืด Laravel อนุญาตให้เราสร้างไฟล์ View (Blade) ขึ้นมาสวมทับหน้าตาเหล่านี้ได้ เพื่อรักษาภาพลักษณ์ (Branding) ของแอปพลิเคชันเราเอาไว้ - 📝 ระบบกล่องดำ (Laravel Logging):
Laravel ใช้ไลบรารีที่ชื่อว่า Monolog อยู่เบื้องหลัง มันมีระดับความรุนแรงของ Log ตามมาตรฐานสากล (RFC 5424) ถึง 8 ระดับ แต่ที่เราใช้กันบ่อยๆ ในชีวิตประจำวันมี 2 ตัวคือ:
info(): เอาไว้จดบันทึก “เหตุการณ์ปกติที่สำคัญ” (เช่น ลูกค้า A โอนเงินสำเร็จแล้ว)error(): เอาไว้จดบันทึก “ตอนระบบพัง หรือจับ Exception ได้” เพื่อให้เราตามรอยได้ง่ายๆ

4. 💻 ร่ายมนต์โค้ด (Show me the Code):
พาร์ท A: การตกแต่งหน้า Error ให้สวยงาม (Custom Error Pages)
สมมติว่ามีคนพยายามเข้า URL ที่ไม่มีอยู่จริง ระบบจะโยน Error 404 ออกมา เรามาสร้างหน้าเพจปลอบใจลูกค้ากันครับ
สเต็ปที่ 1: สั่งให้ Artisan คายไฟล์ Template หน้า Error พื้นฐานออกมาให้เราแก้
# รันคำสั่งนี้ใน Terminal
php artisan vendor:publish --tag=laravel-errorsสเต็ปที่ 2: เข้าไปที่โฟลเดอร์ resources/views/errors/ น้องจะเห็นไฟล์เช่น 404.blade.php, 500.blade.php โผล่ขึ้นมา เราสามารถเปิดเข้าไปแก้ HTML ให้เป็นดีไซน์ของเว็บเราได้เลยครับ
<!-- resources/views/errors/404.blade.php -->
@extends('layouts.app')
@section('content')
<div class="text-center mt-20">
<img src="/images/crying-cat.png" alt="Not Found">
<h1 class="text-4xl font-bold">404 - ขออภัย ไม่พบหน้าที่คุณตามหา</h1>
<p>ดูเหมือนว่าคุณจะหลงทาง... กลับหน้าแรกกันเถอะ</p>
<!-- เราสามารถดึงข้อความ Error ที่ระบบส่งมาให้ด้วยตัวแปร $exception ได้ -->
<p class="text-gray-500">{{ $exception->getMessage() }}</p>
<a href="/" class="btn btn-primary">กลับหน้าแรก</a>
</div>
@endsectionทริคเพิ่มเติม: เวลาน้องเขียน Controller ถ้าน้องอยาก “ถีบ” ผู้ใช้ออกไปหน้า 404 น้องสามารถใช้ Helper function โยนออกไปตรงๆ ได้เลยครับ:
// โยนไปหน้า 404 ทันที พร้อมฝากข้อความไปด้วย
abort(404, 'สินค้านี้ถูกลบออกจากระบบไปแล้วครับ');
พาร์ท B: การเขียน Log เพื่อสืบสวนคดี
เรามาดูวิธีการใช้ info() และ error() ภายใน Controller กันครับ
<?php
namespace App\Http\Controllers;
use App\Models\Order;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log; // ดึง Facade มาใช้งาน
use Throwable;
class PaymentController extends Controller
{
public function process(Request $request, $orderId)
{
// 1. บันทึก "ข้อมูลทั่วไป" เพื่อให้รู้ว่า Process เริ่มทำงานแล้ว (ใช้ Helper function ก็ได้)
info('เริ่มกระบวนการชำระเงิน', ['order_id' => $orderId, 'user' => $request->user()->id]);
try {
// ดึงข้อมูลออเดอร์
$order = Order::findOrFail($orderId);
// ... สมมติว่ามี Logic ตัดบัตรเครดิตที่นี่ ...
// 2. ถ้าสำเร็จ บันทึกไว้เป็นหลักฐาน
Log::info('ตัดบัตรเครดิตสำเร็จ', ['order_id' => $orderId]);
return view('payment.success');
} catch (Throwable $e) {
// 3. ถ้าระบบพัง (เช่น ต่อ API ธนาคารไม่ได้) ให้จับ Exception ไว้
// และใช้ Log::error() บันทึกข้อความ พร้อมโยน Object Exception ยัดเข้าไปใน Context ด้วย
Log::error('ระบบตัดบัตรพังจ้า!', [
'order_id' => $orderId,
'error_message' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine()
]);
// 4. โยนหน้า 500 กลับไปให้ลูกค้าดู
abort(500, 'ขออภัย ระบบชำระเงินขัดข้องชั่วคราว ทีมงานกำลังแก้ไขครับ');
}
}
}ผลลัพธ์: เมื่อเกิดเหตุการณ์ขึ้น ให้เราเปิดไฟล์ storage/logs/laravel.log ดูครับ เราจะเห็นข้อมูลสืบสวนคดีเรียงกันอย่างสวยงาม ทำให้แก้บั๊กได้ตรงจุด ไม่ต้องงมเข็มในมหาสมุทร
5. 🛡️ เคล็ดลับจากคัมภีร์ลับ (Under the Hood / Pro-Tips):
ในฐานะ Senior Dev พี่มีทริคเด็ดๆ เกี่ยวกับการจัดการ Logs มาฝากครับ:
- 🗂️ เปลี่ยนไปใช้ Log แบบรายวัน (Daily Channel):
ตามค่าเริ่มต้น Laravel จะเก็บ Log ยัดลงในไฟล์
laravel.logไฟล์เดียว ถ้าเว็บคนเข้าเยอะ ไฟล์นี้อาจจะใหญ่ถึง 10GB! เปิดอ่านทีคอมค้าง พี่แนะนำให้เข้าไปแก้ไฟล์.envเปลี่ยนค่าLOG_CHANNEL=stack(หรือ single) ให้กลายเป็นLOG_CHANNEL=dailyครับ ระบบจะสร้างไฟล์ใหม่ให้ทุกวัน (เช่นlaravel-2026-03-11.log) และจะลบไฟล์ที่เก่ากว่า 14 วันทิ้งให้อัตโนมัติ สบายเซิร์ฟเวอร์สุดๆ - 📣 การรายงาน Error โดยไม่หยุดการทำงาน (
report()): บางครั้งเกิด Error ขึ้น เราอยาก “จดลง Log” แต่ “ไม่อยากให้หน้าเว็บพัง (ไม่อยาก abort)” เราสามารถใช้ฟังก์ชันreport($e);ได้ครับ มันจะแอบเอา Exception ไปจดลง Log ให้เบื้องหลัง แล้วปล่อยให้โค้ดบรรทัดต่อไปทำงานต่อได้อย่างเนียนๆ - Slack / Discord Alerts:
รู้ไหมว่า Log ของ Laravel ทรงพลังขนาดที่ว่าเราตั้งค่า
config/logging.phpให้มันโยน Log ระดับcriticalยิงเข้าห้องแชท Slack หรือ Discord ของทีม Developer ให้เด้งเตือนในมือถือทันทีได้เลยนะ! (ลองไปเล่นดูใน Channel Slack ครับ)
6. 🏁 บทสรุป (To be continued…):
จะเห็นได้ว่า Error Handling และ Logging เป็นสองสิ่งที่คู่กันเหมือนหยินหยางครับ ฝั่งหนึ่งเอาไว้ปกป้องหน้าตาของแบรนด์ (Custom Views) ไม่ให้ลูกค้าเห็นโค้ดดิบๆ อีกฝั่งเอาไว้เป็นอาวุธให้โปรแกรมเมอร์ (Logs) เข้าไปผ่าตัดรักษาโรคได้อย่างแม่นยำ
จงจำไว้ว่า “บั๊กเป็นเรื่องธรรมชาติ แต่การปล่อยให้บั๊กเกิดขึ้นโดยที่เราไม่รู้อะไรเลย เป็นความผิดของโปรแกรมเมอร์ครับ!”
เมื่อแอปพลิเคชันของเราแข็งแกร่งและตรวจสอบได้แล้ว… ในตอนต่อไป พี่จะพาไปงัดข้อกับเรื่องที่เกี่ยวข้องกับ “เวลา” บ้าง ถ้าน้องมีโค้ดที่รันช้ามากๆ (เช่น การแปลงไฟล์วิดีโอ) เราจะทำอย่างไรให้ลูกค้าไม่ต้องนั่งรอหน้าจอโหลดค้าง? เตรียมตัวพบกับสุดยอดสถาปัตยกรรมเบื้องหลังอย่าง “Queues & Jobs (ระบบคิว)” ชงกาแฟแก้วใหม่ แล้วพบกันครับ!
ต้องการที่ปรึกษาและพัฒนาระบบ Automation ให้กับโรงงานของคุณ? ทีมงาน WP Solution พร้อมให้บริการออกแบบและติดตั้งระบบแบบครบวงจร ดูรายละเอียดบริการของเราได้ที่: www.wpsolution2017.com หรือพูดคุยปรึกษาเบื้องต้นได้ที่ Line: wisit.p