WordPress ขึ้น 500 บางหน้า แต่ debug.log ว่าง — fatal จริงอยู่ที่ apache log
log ว่างไม่ได้แปลว่าไม่มี error — fatal ที่เกิดก่อนระบบ logging ของ WordPress พร้อมทำงาน จะไม่มีวันโผล่ใน debug.log เคสนี้เป็นตัวอย่างที่ดีว่าความจริงสุดท้ายอยู่ที่ log ของ web server เสมอ
พอดีมีเว็บ WordPress ของหน่วยงานหนึ่งอาการประหลาดครับ: หน้าแรกปกติ หน้าบทความปกติ แต่เฉพาะหน้า portfolio ทุกหน้า (/portfolio-items/อะไรก็ตาม/) ขึ้น 500 หมด
ผมเปิด WP_DEBUG_LOG รอไว้แล้วกดหน้า 500 ซ้ำ — debug.log ว่างเปล่า ไม่มีอะไรเข้าเลย ตรงนี้แหละที่หลายคนหลงทาง เพราะสัญชาตญาณบอกว่า "log ว่าง = ไม่มี error" จริงๆ คือ:
Fatal ที่เกิดตอน theme กำลัง render เกิดก่อนที่ระบบ logging ของ WP จะพร้อมทำงาน — debug.log เลยไม่มีวันเห็นมัน อย่าเพิ่งสรุปว่าไม่มี error
fatal ตัวจริงอยู่ใน apache error log
โฮสติ้งที่รัน PHP-FPM ผ่าน apache (mod_proxy_fcgi) จะมี log ต่อโดเมนอยู่ที่:
tail -50 /var/log/httpd/domains/example-site.org.error.log
เจอทันที:
[proxy_fcgi:error] AH01071: Got error 'PHP message: PHP Fatal error:
Uncaught Error: Call to undefined method Avada_Layout::add_class()
in /home/user/domains/example-site.org/public_html/wp-content/themes/my-child-theme/single-avada_portfolio.php:18'
ชัดเลยครับ — child theme มีไฟล์ single-avada_portfolio.php ที่เรียก method ที่ไม่มีอยู่แล้ว
เว็บที่ log เยอะๆ หาตัวการแบบเป็นระบบได้ด้วยบรรทัดเดียว:
grep 'Fatal' /var/log/httpd/domains/example-site.org.error.log \
| grep -oE '/wp-content/(plugins|themes)/[^/ ]+' | sort | uniq -c | sort -rn
ได้คำตอบทันทีว่า fatal กระจุกอยู่ theme/plugin ตัวไหน
ทำไมถึงพัง — โรคประจำตัวของ child theme
ไล่ประวัติแล้วเรื่องเป็นแบบนี้ครับ: คนทำเว็บเมื่อ 2 ปีก่อนก๊อปไฟล์ template จาก parent theme (Avada) มาแก้ใน child theme ซึ่งเป็นวิธีมาตรฐานของ WP ไม่ผิดอะไร — แต่ไฟล์ก๊อปนั้นเรียก internal API ของ Avada เวอร์ชันนั้น (Avada()->layout->add_class())
เวลาผ่านไป Avada อัปเดตมาเรื่อยๆ จนเวอร์ชันปัจจุบันลบ method นั้นทิ้ง — template อื่นของ parent ถูกอัปเดตตาม แต่ไฟล์ก๊อปใน child theme ไม่มีใครแตะ หน้าไหนใช้ template นั้น = fatal ทันที
เช็ค blast radius ก่อนแก้ — child theme เรียก API ที่ตายแล้วอีกกี่ไฟล์:
grep -rln 'add_class\|add_style' wp-content/themes/my-child-theme/
# โชคดี: ไฟล์เดียว
วิธีแก้ที่เลือก: rename ให้ fallback
ผมไม่แก้โค้ดในไฟล์ทีละ method ครับ เพราะไฟล์ 11KB นั้นอาจเรียก API ที่ถูกลบไปอีกหลายจุด แก้ตัวหนึ่งเจอตัวถัดไป ไม่จบ ทางที่เสถียรกว่า:
cd wp-content/themes/my-child-theme
mv single-avada_portfolio.php single-avada_portfolio.php.disabled-2026-07-04
หลักการ: template hierarchy ของ WP เมื่อไม่เจอไฟล์ใน child จะ fallback ไป parent — Avada รุ่นใหม่จัดการ portfolio ผ่านระบบ template ของตัวเองอยู่แล้ว ผลคือหน้า portfolio กลับมา 200 เนื้อหาแสดงครบ เพียง layout เป็นแบบ default ของ Avada แทนแบบ custom เก่า (ซึ่งเจ้าของเว็บโอเค)
ข้อดีคือ reversible 100% — อยากได้ custom layout คืนก็ mv กลับแล้วค่อยนั่ง port โค้ดตาม API ใหม่ ตามสะดวก
เปิด WP_DEBUG อย่างปลอดภัยบนเว็บ production
แถมท้ายครับ เวลาต้อง debug เว็บจริงที่มีคนใช้งาน:
// wp-config.php — backup ไฟล์ก่อนแก้เสมอ
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false); // สำคัญ! อย่าโชว์ error ให้คนเข้าเว็บเห็น
แล้ว php -l wp-config.php ก่อนทุกครั้ง — พลาด syntax ตัวเดียวเว็บขาวทั้งเว็บ และอย่าลืมว่าตามที่เล่าข้างบน fatal ระดับ theme-load อาจไม่เข้า debug.log อยู่ดี apache error log คือแหล่งความจริงสุดท้าย
สรุปเป็นเช็คลิสต์
- 500 เฉพาะบางประเภทหน้า + debug.log ว่าง = fatal เกิดก่อน WP logging — อย่าเชื่อ log ว่าง
- ความจริงอยู่ที่
/var/log/httpd/domains/<domain>.error.log— มองหา proxy_fcgi + PHP Fatal grep -oE '/wp-content/...' | sort | uniq -cหา culprit- child theme ที่ก๊อป template จาก parent = ระเบิดเวลาทุกครั้งที่ parent อัปเดตใหญ่
- แก้ด้วยการ rename ให้ fallback ก่อน (reversible) ค่อยตัดสินใจ port โค้ด
ส่วนตัวผมเจอโรค child theme แบบนี้มาหลายเว็บแล้ว ใครรับดูแลเว็บ WP ต่อจากคนอื่น ไล่เช็คไฟล์ก๊อปใน child theme ไว้ก่อนเลยครับ ตรงไหนผมอธิบายตกหล่นหรือพิมพ์ผิด เดี๋ยวกลับมาแก้เพิ่มให้ภายหลังครับ
อยากให้เราทำให้ไหม?
ให้เราช่วยติดตั้ง ตั้งค่า ย้ายระบบ หรือแก้ปัญหาเซิร์ฟเวอร์ เพื่อให้คุณมีเวลาไปทำงานที่สำคัญกว่า
เคยเจองานแบบนี้ไหม? ติดตรงไหน?
มาแลกวิธีกันต่อในบอร์ด LinuxThai



ความคิดเห็น 0
ยังไม่มีความคิดเห็น — เป็นคนแรกเลย