ข้ามไปยังเนื้อหา
เซิร์ฟเวอร์และ .htaccess

โพสต์ WordPress ขึ้น 404 แต่หน้าแรกเปิดได้ปกติ

ถ้าหน้าแรกโหลดได้ปกติแต่โพสต์และหน้าเดี่ยว ๆ ทุกหน้าขึ้น 404 แสดงว่ากฎ URL rewrite ที่ WordPress ต้องใช้หายไปหรือเสียในไฟล์ของคุณ

เผยแพร่แล้ว

ถ้าหน้าแรกโหลดได้ปกติ แต่โพสต์และหน้าเดี่ยว ๆ ทุกหน้าขึ้น 404 แสดงว่ากฎ URL rewrite ที่ WordPress ต้องพึ่งพานั้นหายไปหรือเสียในไฟล์ .htaccess ของคุณ วิธีแก้ที่เร็วที่สุด: เข้าไปที่ Settings → Permalinks ใน wp-admin แล้วกด Save Changes โดยไม่ต้องแก้อะไรเลย นั่นจะบังคับให้ WordPress สร้างบล็อก rewrite ขึ้นมาใหม่ ถ้ายังขึ้น 404 อยู่ แสดงว่าไฟล์ .htaccess ของคุณเว็บเซิร์ฟเวอร์เขียนไม่ได้ หรือ Apache ถูกตั้งค่าให้เมินไฟล์นี้ หรือคุณกำลังใช้ Nginx (ซึ่งไม่ใช้ .htaccess เลย)

ทำไมหน้าแรกเปิดได้แต่โพสต์เปิดไม่ได้

หน้าแรกของคุณเปิดได้เพราะคำขอไปที่ / ถูกเสิร์ฟตรงจาก index.php ที่ document root โดยไม่ต้อง rewrite อะไรเลย

แต่คำขอไปที่ /2026/my-post/ ต่างออกไป พาธนั้นไม่ใช่โฟลเดอร์จริงบนดิสก์ การที่ WordPress จะตอบคำขอนี้ได้ Apache ต้องroute คำขอภายในไปที่ index.php จากนั้น WordPress จึงอ่าน REQUEST_URI เอาไปเทียบกับกฎ rewrite ที่เก็บอยู่ในตัวเลือก rewrite_rules ในฐานข้อมูล แล้วแปลง query vars (WP::parse_request()) และโหลดโพสต์ที่ถูกต้อง

จุดที่พังคือการส่งต่อจาก Apache ไปยัง index.php ซึ่งขึ้นอยู่กับบล็อกนี้ใน .htaccess ล้วน ๆ:

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

บรรทัด RewriteCond สองบรรทัดมีความหมายว่า: ถ้าพาธที่ร้องขอไม่ใช่ไฟล์จริง (!-f) และไม่ใช่ไดเรกทอรีจริง (!-d) ให้ส่งไปที่ index.php ลบบล็อกนี้ออกเมื่อไร Apache จะไปมองหาไดเรกทอรีชื่อ /2026/my-post/ จริง ๆ หาไม่เจอ แล้วคืนค่า 404 ของตัวเอง — ก่อนที่ WordPress จะได้เห็นคำขอด้วยซ้ำ

นี่คือส่วนที่คู่มือส่วนใหญ่ข้ามไป เมื่อคุณกด Save ในหน้า Permalinks WordPress จะเรียก flush_rewrite_rules() บน Apache ที่ .htaccess เขียนได้ คำสั่งนี้จะไปกระตุ้น save_mod_rewrite_rules() ซึ่งสร้างบล็อกด้านบนขึ้นมาใหม่ผ่าน WP_Rewrite::mod_rewrite_rules() แล้วเขียนกลับลงไฟล์ด้วย insert_with_markers()

insert_with_markers() จะแตะต้องเฉพาะบรรทัดที่อยู่ระหว่าง # BEGIN WordPress กับ # END WordPress เท่านั้น ทุกอย่างที่อยู่นอกเครื่องหมายเหล่านี้จะถูกปล่อยไว้ไม่ยุ่ง ส่วนทุกอย่างที่อยู่ข้างในจะถูกทิ้งแล้วเขียนใหม่ WordPress เวอร์ชันใหม่ ๆ ถึงกับพิมพ์คำเตือนไว้ในไฟล์ตรง ๆ เลย:

Any changes to the directives between these markers will be overwritten.

ดังนั้นคำที่ว่า “WordPress เขียนทับ .htaccess ของฉัน” เป็นความจริง แต่ในขอบเขตแคบ ๆ: มันเขียนทับเฉพาะบล็อกที่มีเครื่องหมายของตัวเอง และเฉพาะตอนที่ไฟล์เขียนได้เท่านั้น ถ้าไฟล์เขียนไม่ได้ การบันทึกจะไม่มีผลอะไรกับดิสก์เลยแบบเงียบ ๆ WordPress จะแสดงประกาศสีเหลืองในหน้า Permalinks บอกให้คุณวางกฎด้วยตนเอง และถ้าคุณพลาดประกาศนั้น บล็อก rewrite ของคุณก็จะยังหายไป และทุกโพสต์ก็จะขึ้น 404 ต่อไป

วิธีแก้ทีละขั้น

1. บันทึก permalinks ใหม่ Settings → Permalinks → Save Changes ไม่ต้องแก้อะไร ขั้นตอนนี้จะรัน flush อีกครั้งและเขียนบล็อกขึ้นมาใหม่ ซึ่งแก้ปัญหาได้เกือบทุกกรณี รวมถึงกฎที่ค้างเก่าหลังการย้ายเว็บ

2. เช็กว่า .htaccess มีอยู่จริงและเขียนได้ ไฟล์นี้อยู่ในโฟลเดอร์เดียวกับ wp-config.php มันเป็นไฟล์ dotfile ดังนั้นต้องเปิด “show hidden files” ใน FTP client ของคุณ หรือใช้:

ls -la /path/to/wordpress/.htaccess

ถ้าไฟล์หายไป ให้สร้างขึ้นมาแล้ววางบล็อกที่ถูกต้อง ถ้าการติดตั้งของคุณอยู่ในไดเรกทอรีย่อย RewriteBase และปลายทาง rewrite สุดท้ายต้องตรงกับพาธนั้น — การตั้งค่านี้ผิดเป็นสาเหตุที่พบบ่อยที่สุดที่บล็อกซึ่งวางเองยังขึ้น 404 ตัวสร้าง .htaccess ของเราจะสร้างบล็อกที่ตรงกับพาธการติดตั้งของคุณเป๊ะ ๆ คุณจะได้ไม่ต้องเดา

3. ยืนยันว่า Apache ได้รับอนุญาตให้อ่าน .htaccess ถ้า virtual host ตั้งค่า AllowOverride None ไว้ Apache จะเมินไฟล์นี้โดยสิ้นเชิงไม่ว่าข้างในจะมีอะไรก็ตาม คุณต้องตั้ง AllowOverride All (หรืออย่างน้อย FileInfo) บนไดเรกทอรีของ WordPress ค่านี้อยู่ในการตั้งค่าเซิร์ฟเวอร์ ไม่ได้อยู่ใน .htaccess ดังนั้นต้องมีสิทธิ์เข้าถึงเซิร์ฟเวอร์:

<Directory /var/www/html>
    AllowOverride All
</Directory>

4. ยืนยันว่า mod_rewrite เปิดใช้งานอยู่ บน Debian/Ubuntu:

sudo a2enmod rewrite
sudo systemctl restart apache2

5. บน Nginx ไม่มี .htaccess กฎ rewrite จะไปอยู่ใน server block แทน:

location / {
    try_files $uri $uri/ /index.php?$args;
}

วิธีวินิจฉัยเร็ว ๆ: 404 นี้เป็นของใคร?

ดูที่หน้า 404 ถ้าเป็นหน้า error ของ Apache หรือของโฮสต์ที่ไม่มีสไตล์ใด ๆ แสดงว่า Apache ไปไม่ถึง WordPress เลย — นั่นคือปัญหาของ .htaccess หรือการตั้งค่าเซิร์ฟเวอร์ (ขั้นตอน 2–4) แต่ถ้าเป็นหน้า 404 ที่มีสไตล์ ของธีมคุณเอง แสดงว่า WordPress รับคำขอแล้วแต่จับคู่ไม่ได้ — กฎในฐานข้อมูลค้างเก่า และการบันทึก permalinks ใหม่ (ขั้นตอน 1) คือทางแก้ ความแตกต่างจุดเดียวนี้ช่วยคนส่วนใหญ่ประหยัดเวลาเดาไปเป็นชั่วโมง

สิ่งที่ไม่ควรทำ

อย่าเพิ่งปิด ปลั๊กอิน wordpress ทั้งหมด อาการที่เป็น “โพสต์ 404 หน้าแรกปกติ” ล้วน ๆ คือปัญหา rewrite ไม่ใช่ปลั๊กอินตีกัน การปิดปลั๊กอินเป็นคำตอบสำเร็จรูปตามฟอรัม แต่แทบไม่เคยแตะปัญหานี้ได้เลย

อย่า chmod 777 ไฟล์ .htaccess ของคุณ WordPress ต้องการให้ไฟล์เขียนได้โดย ผู้ใช้ที่เป็นเว็บเซิร์ฟเวอร์ ซึ่งไม่ใช่เรื่องเดียวกับการเปิดให้ทั้งโลกเขียนได้ ตั้ง 644 พร้อมเจ้าของที่ถูกต้องก็ปลอดภัยและใช้ได้ ส่วน 777 เป็นช่องโหว่ความปลอดภัยที่ยังไงก็แก้ปัญหา routing ไม่ได้อยู่ดี

อย่าวางกฎ rewrite ที่กำหนดเองไว้ในระหว่างเครื่องหมาย # BEGIN WordPress / # END WordPress มันจะถูกลบทิ้งครั้งต่อไปที่มีใครบันทึก permalinks ให้วาง directive ที่กำหนดเองไว้ เหนือ บรรทัด # BEGIN WordPress

อย่าติดตั้ง WordPress ใหม่ ไฟล์แกนหลักไม่ได้มีปัญหาอะไร นี่เป็นแค่ข้อความบล็อกเดียวที่หายไป ไม่ใช่การติดตั้งที่เสียหาย

อย่าโทษธีมของคุณ การ route permalink เป็นส่วนแกนหลักของ WordPress ธีมไม่สามารถทำให้เกิดปัญหานี้ได้ และก็แก้ไม่ได้เช่นกัน

ยังติดอยู่?

ถ้าคุณบันทึก permalinks ใหม่แล้ว ยืนยันแล้วว่าบล็อกมีอยู่จริงและเขียนได้ และตั้ง AllowOverride All แล้ว ผู้ต้องสงสัยที่เหลือคือปลั๊กอินด้านความปลอดภัยหรือกฎระดับโฮสต์ที่คอยสร้างใหม่หรือล็อก .htaccess ไว้ลับหลังคุณ เช็กเวลาแก้ไขล่าสุดของไฟล์ทันทีหลังบันทึก permalinks — ถ้ามันไม่เปลี่ยน แสดงว่ามีบางอย่างบล็อกการเขียนอยู่ สร้างบล็อกที่สะอาดขึ้นมาใหม่ด้วย ตัวสร้าง .htaccess วางลงไป แล้วทดสอบใหม่ด้วยการรีเฟรชแบบ hard refresh