ดัชนี Hooks ของ WordPress
ดัชนีที่ค้นหาได้ของ action และ filter ของ WordPress ที่นักพัฒนาใช้งานจริง — พร้อมซิกเนเจอร์ add_action/add_filter ที่แม่นยำ ช่วงเวลาที่มันทำงาน ตัวอย่างที่ใช้ได้จริง และจุดที่มักเล่นงานคนใช้
ฮุก 39 ตัว พร้อมซิกเนเจอร์ add_action / add_filter ที่ถูกต้องแม่นยำ ตำแหน่งที่มันทำงาน ตัวอย่างที่ใช้ได้จริง และจุดที่มักทำคนพลาดกัน 1 ตัวถูกทำเครื่องหมายว่ายังไม่ยืนยัน — เรายังไม่ได้ตรวจสอบจำนวนอาร์กิวเมนต์ของมันเทียบกับซอร์สโค้ดของ WordPress และเราขอแจ้งเตือนไว้ดีกว่าจะนำเสนอสิ่งที่เดาเอาว่าเป็นข้อเท็จจริง
รายการนี้ไม่ได้ครบถ้วนทั้งหมดและไม่ได้ตั้งใจจะเป็นเช่นนั้น — WordPress มีฮุกอยู่หลายพันตัว รายการนี้ครอบคลุมเฉพาะตัวที่คนหยิบมาใช้งานกันจริง ๆ
ทำงานหลังจาก WordPress โหลดเสร็จแล้วแต่ก่อนที่จะส่ง header ใด ๆ ออกไป เป็นที่มาตรฐานสำหรับลงทะเบียน custom post type, taxonomy และ rewrite rule
ทำงานเมื่อ
ในทุกคำขอ ทั้งฝั่งหน้าเว็บและหน้าแอดมิน หลังจากที่คอร์ ปลั๊กอิน และธีมถูกโหลดแล้ว
ซิกเนเจอร์
add_action( 'init', 'my_callback' );ตัวอย่าง
add_action( 'init', function () {
register_post_type( 'book', array(
'public' => true,
'label' => 'Books',
'show_in_rest' => true, // required for the block editor
) );
} );จุดที่ต้องระวัง
init ทำงานในทุกคำขอ รวมถึง AJAX, REST และ cron การทำอะไรที่ช้าตรงนี้ (เรียก HTTP หรือคิวรีหนัก ๆ) จะถ่วงการโหลดทุกหน้าโดยไม่มีข้อยกเว้น อีกอย่าง: ผู้ใช้ปัจจุบันเรียกใช้ได้แล้วตรงนี้ แต่คุณยังส่งเอาต์พุตออกไปไม่ได้ — header ยังไม่ถูกส่ง แต่กำลังจะส่งแล้ว
ทำงานเมื่อธีมถูกโหลดแล้ว เป็นที่ที่ถูกต้องสำหรับ add_theme_support(), add_image_size() และการลงทะเบียนเมนูนำทาง
ทำงานเมื่อ
หลังจากไฟล์ functions.php ของธีมถูกโหลด แต่ก่อน init
ซิกเนเจอร์
add_action( 'after_setup_theme', 'my_callback' );ตัวอย่าง
add_action( 'after_setup_theme', function () {
add_theme_support( 'post-thumbnails' );
add_theme_support( 'title-tag' );
add_image_size( 'card', 600, 400, true ); // true = hard crop
} );จุดที่ต้องระวัง
การลงทะเบียนขนาดรูปภาพที่ init แทนที่จะเป็นตรงนี้ ส่วนใหญ่ใช้งานได้เพราะบังเอิญ แล้วก็ล้มเหลวอย่างลึกลับในบางกรณี ใช้ after_setup_theme เถอะ — มันมีไว้เพื่อการนี้
ทำงานเมื่อปลั๊กอินที่เปิดใช้งานทั้งหมดถูกโหลดแล้ว เป็นจุดที่ปลอดภัยที่สุดในการเริ่มโต้ตอบกับปลั๊กอินตัวอื่น
ทำงานเมื่อ
หลังจากไฟล์ปลั๊กอินทุกไฟล์ถูกรวมเข้ามาแล้ว แต่ก่อนที่ธีมจะถูกโหลด
ซิกเนเจอร์
add_action( 'plugins_loaded', 'my_callback' );จุดที่ต้องระวัง
ผู้ใช้ปัจจุบันยังเรียกใช้ไม่ได้ตรงนี้ — wp_get_current_user() จะทำงานได้ไม่น่าเชื่อถือ ถ้าต้องการข้อมูลผู้ใช้ ให้ใช้ init
ทำงานหลังจาก WordPress โหลดครบสมบูรณ์ — ปลั๊กอิน ธีม init และผู้ใช้พร้อมทั้งหมด
ทำงานเมื่อ
หลังจาก init และหลังจากที่ผู้ใช้ปัจจุบันถูกตั้งค่าแล้ว
ซิกเนเจอร์
add_action( 'wp_loaded', 'my_callback' );ทำงานตอนเริ่มของทุกคำขอฝั่งแอดมิน ใช้สำหรับ register_setting() การตรวจสิทธิ์ และการรีไดเรกต์ในหน้าแอดมิน
ทำงานเมื่อ
ในทุกคำขอฝั่งแอดมิน
ซิกเนเจอร์
add_action( 'admin_init', 'my_callback' );จุดที่ต้องระวัง
มันทำงานกับคำขอ admin-ajax.php ด้วย ซึ่งไม่ได้เป็น "หน้าจอแอดมิน" จริง ๆ ถ้า callback ของคุณสมมติว่ามีหน้าจออยู่ ให้ป้องกันไว้ด้วย wp_doing_ajax()
ที่เดียวที่ถูกต้องสำหรับ enqueue CSS และ JavaScript ฝั่งหน้าเว็บ
ทำงานเมื่อ
เมื่อโหลดหน้าเว็บฝั่งหน้าบ้าน ก่อนที่ส่วน head จะถูกเรนเดอร์
ซิกเนเจอร์
add_action( 'wp_enqueue_scripts', 'my_callback' );ตัวอย่าง
add_action( 'wp_enqueue_scripts', function () {
wp_enqueue_style(
'child-style',
get_stylesheet_uri(),
array( 'parent-style' ), // load AFTER the parent
wp_get_theme()->get( 'Version' ) // cache-bust on version change
);
} );จุดที่ต้องระวัง
แม้ชื่อจะบอกว่าสคริปต์ แต่มันจัดการ STYLE ด้วยเช่นกัน — ไม่มีฮุกชื่อ wp_enqueue_styles และหลายคนเสียเวลาไปกับการตามหามัน อีกอย่าง: มันไม่ทำงานในหน้าแอดมิน (ให้ใช้ admin_enqueue_scripts) หรือในตัวแก้ไขบล็อก (ให้ใช้ enqueue_block_editor_assets)
Enqueue CSS/JS ในหน้าแอดมิน รับ hook suffix ของหน้าจอปัจจุบันมาด้วย คุณจึงโหลด asset เฉพาะบนหน้าจอเดียวได้
ทำงานเมื่อ
เมื่อโหลดหน้าแอดมิน
ซิกเนเจอร์
add_action( 'admin_enqueue_scripts', 'my_callback' ); // receives $hook_suffixตัวอย่าง
add_action( 'admin_enqueue_scripts', function ( $hook ) {
if ( 'settings_page_my-plugin' !== $hook ) {
return; // do not load our JS on every admin screen
}
wp_enqueue_script( 'my-admin', plugins_url( 'admin.js', __FILE__ ), array(), '1.0', true );
} );จุดที่ต้องระวัง
การไม่ป้องกันด้วย $hook เป็นสาเหตุที่พบบ่อยที่สุดที่ทำให้ปลั๊กอินไปทำหน้าจอแอดมินอื่น ๆ ที่ไม่เกี่ยวข้องพัง โหลด asset ของคุณเฉพาะที่ที่จำเป็นเท่านั้น และห้ามที่อื่น
Enqueue asset เข้าไปในตัวแก้ไขบล็อก (Gutenberg) เท่านั้น — ไม่ใช่ฝั่งหน้าเว็บ ไม่ใช่ส่วนอื่นของหน้าแอดมิน
ทำงานเมื่อ
เมื่อตัวแก้ไขบล็อกโหลด
ซิกเนเจอร์
add_action( 'enqueue_block_editor_assets', 'my_callback' );พิมพ์เอาต์พุตเข้าไปใน <head> ใช้สำหรับ meta tag และ critical CSS แบบ inline
ทำงานเมื่อ
ภายใน <head> บนฝั่งหน้าเว็บ
ซิกเนเจอร์
add_action( 'wp_head', 'my_callback' );จุดที่ต้องระวัง
อย่า enqueue สคริปต์หรือสไตล์ตรงนี้ — ให้ใช้ wp_enqueue_scripts ซึ่งปล่อยให้ WordPress จัดการเรื่อง dependency และการตัดตัวซ้ำเอง การ echo แท็ก <script> เข้าไปใน wp_head จะข้ามทั้งหมดนั้น และเป็นเหตุผลว่าทำไมหลายเว็บถึงโหลด jQuery ซ้ำถึงสามครั้ง
พิมพ์เอาต์พุตก่อน </body> เล็กน้อย เป็นที่ที่เหมาะสำหรับสคริปต์ analytics และมาร์กอัปที่หน่วงไว้
ทำงานเมื่อ
ที่ท้ายของหน้าเว็บฝั่งหน้าบ้าน
ซิกเนเจอร์
add_action( 'wp_footer', 'my_callback' );จุดที่ต้องระวัง
ธีมที่ลืมเรียก wp_footer() จะทำให้แถบแอดมินพัง ทำให้ปลั๊กอินใด ๆ ที่ enqueue สคริปต์ท้ายหน้าพัง และถูกปฏิเสธโดยอัตโนมัติในการตรวจธีมของ wordpress.org
กรองเนื้อหาโพสต์ก่อนที่จะแสดงผลทันที เป็นที่ปกติสำหรับต่อท้ายหรือเติมหน้ามาร์กอัปให้กับโพสต์
ทำงานเมื่อ
ทุกครั้งที่มีการเรียก the_content()
ซิกเนเจอร์
add_filter( 'the_content', 'my_callback' ); // receives $contentตัวอย่าง
add_filter( 'the_content', function ( $content ) {
if ( ! is_singular( 'post' ) || ! in_the_loop() || ! is_main_query() ) {
return $content; // <- the guard everyone forgets
}
return $content . '<p class="cta">Enjoyed this? Read more.</p>';
} );จุดที่ต้องระวัง
มันทำงานบ่อยกว่าที่คุณคิดมาก — ในวิดเจ็ต ในการตอบกลับของ REST ในการสร้าง excerpt ของปลั๊กอินบางตัว และหนึ่งครั้งต่อโพสต์ในลูปของหน้าคลังบทความ หากไม่มีตัวป้องกัน is_singular / in_the_loop / is_main_query ปุ่ม CTA ของคุณจะโผล่สิบห้าครั้งบนหน้าดัชนีบล็อกและใน RSS feed นี่คือ filter ที่ถูกใช้ผิดมากที่สุดใน WordPress
กรองหัวข้อโพสต์ก่อนแสดงผล
ทำงานเมื่อ
ทุกครั้งที่มีการเรียก the_title() หรือ get_the_title()
ซิกเนเจอร์
add_filter( 'the_title', 'my_callback', 10, 2 ); // receives $title, $post_idจุดที่ต้องระวัง
มันทำงานกับหัวข้อในเมนูแอดมิน ในเมนูนำทาง และใน <title> ของเอกสารด้วย การกรองมันโดยไม่มีเงื่อนไขจะเปลี่ยนชื่อสิ่งต่าง ๆ ในที่ที่คุณไม่ได้ตั้งใจ
กำหนดว่า excerpt ที่สร้างอัตโนมัติจะมีกี่คำ ค่าเริ่มต้นคือ 55
ทำงานเมื่อ
เมื่อ WordPress สร้าง excerpt ให้กับโพสต์ที่ไม่มี excerpt แบบกำหนดเอง
ซิกเนเจอร์
add_filter( 'excerpt_length', 'my_callback' ); // receives $length (words)ตัวอย่าง
add_filter( 'excerpt_length', function ( $length ) {
return 25;
}, 999 ); // high priority: many themes set this too, and last one winsจุดที่ต้องระวัง
มันไม่มีผลกับโพสต์ที่มี excerpt แบบกำหนดเอง — พวกนั้นถูกใช้ตามที่เขียนไว้ทุกตัวอักษร และหลายธีมก็ตั้ง filter นี้เอง คุณจึงมักต้องใช้เลข priority ที่สูงเพื่อเอาชนะ
เปลี่ยนสตริงที่ต่อท้าย excerpt ที่ถูกตัดให้สั้น ค่าเริ่มต้นคือ " […]"
ทำงานเมื่อ
เมื่อ excerpt ที่สร้างอัตโนมัติถูกตัดให้สั้น
ซิกเนเจอร์
add_filter( 'excerpt_more', 'my_callback' ); // receives $moreแก้ไขคิวรีก่อนที่มันจะทำงาน เป็นวิธีที่ถูกต้องในการเปลี่ยนสิ่งที่แสดงบนหน้าคลังบทความ — ดีกว่าการสร้าง WP_Query ตัวที่สองมาก
ทำงานเมื่อ
หลังจากที่ query var ถูกแยกวิเคราะห์ ก่อนที่ SQL จะถูกสร้าง
ซิกเนเจอร์
add_action( 'pre_get_posts', 'my_callback' ); // receives WP_Query $query (by reference)ตัวอย่าง
add_action( 'pre_get_posts', function ( $query ) {
if ( is_admin() || ! $query->is_main_query() ) {
return; // <- both guards are mandatory
}
if ( $query->is_category() ) {
$query->set( 'posts_per_page', 12 );
}
} );จุดที่ต้องระวัง
มันทำงานในหน้าแอดมินด้วย และทำงานกับทุกคิวรี รวมถึงเมนู วิดเจ็ต และคลังสื่อ หากละเว้นตัวป้องกัน is_admin() และ is_main_query() คุณจะเปลี่ยนสิ่งที่รายการโพสต์ในหน้าแอดมินแสดงอย่างเงียบ ๆ — บั๊กที่ตามหาต้นตอได้ยากจริง ๆ อีกข้อสังเกต: ให้แก้ไข $query อย่า return อะไรออกมา
กรองส่วน WHERE ของ SQL ดิบในคิวรี
ทำงานเมื่อ
ระหว่างที่ SQL ของคิวรีกำลังถูกประกอบขึ้น
ซิกเนเจอร์
add_filter( 'posts_where', 'my_callback', 10, 2 ); // receives $where, WP_Query $queryจุดที่ต้องระวัง
คุณกำลังเขียน SQL ดิบ ให้ป้องกันด้วย $query->is_main_query() เสมอ และใช้ $wpdb->prepare() กับข้อมูลนำเข้าจากผู้ใช้เสมอ นี่คือวิธีที่เร็วที่สุดในการเปิดช่อง SQL injection ให้กับเว็บ WordPress
กรองจำนวนโพสต์ทั้งหมดที่คิวรีค้นพบ — ซึ่งเป็นตัวที่ใช้คำนวณการแบ่งหน้า
ทำงานเมื่อ
หลังจากคิวรีทำงาน ก่อนที่การแบ่งหน้าจะถูกคำนวณ
ซิกเนเจอร์
add_filter( 'found_posts', 'my_callback', 10, 2 ); // receives $found_posts, WP_Query $queryกำหนดขนาดพิกเซลที่หากเกินไปแล้ว WordPress จะย่อไฟล์อัปโหลดลงและให้บริการสำเนา "-scaled" แทนไฟล์ต้นฉบับของคุณ ค่าเริ่มต้น 2560
ทำงานเมื่อ
ตอนอัปโหลด เมื่อ WordPress ตัดสินว่ารูปภาพ "ใหญ่" หรือไม่
ซิกเนเจอร์
add_filter( 'big_image_size_threshold', 'my_callback' ); // receives int $thresholdตัวอย่าง
// Serve originals at full resolution — no -scaled copy.
add_filter( 'big_image_size_threshold', '__return_false' );
// Or just raise the ceiling:
add_filter( 'big_image_size_threshold', function () {
return 3840;
} );จุดที่ต้องระวัง
นี่คือสาเหตุที่พบบ่อยที่สุดของ "รูปของฉันดูเบลอหลังจากอัปโหลดขึ้น WordPress" และแทบไม่มีใครรู้ว่ามันมีอยู่ ไฟล์ต้นฉบับของคุณยังอยู่บนดิสก์ — เพียงแต่ไม่เคยถูกให้บริการเท่านั้น โปรดทราบว่ามันใช้กับด้านที่ยาวที่สุด และมีผลเฉพาะกับรูปที่อัปโหลดหลังจากที่ filter นี้ทำงานแล้วเท่านั้น
กรองอาร์เรย์ของขนาดรูปภาพที่ WordPress กำลังจะสร้างให้กับไฟล์อัปโหลด เอาขนาดใดออก (unset) เพื่อหยุดสร้างขนาดนั้น
ทำงานเมื่อ
ตอนอัปโหลด ก่อนที่ไฟล์อนุพันธ์จะถูกสร้าง
ซิกเนเจอร์
add_filter( 'intermediate_image_sizes_advanced', 'my_callback', 10, 2 ); // receives $sizes, $metadataตัวอย่าง
add_filter( 'intermediate_image_sizes_advanced', function ( $sizes ) {
unset( $sizes['1536x1536'] );
unset( $sizes['2048x2048'] );
return $sizes;
} );จุดที่ต้องระวัง
การลบขนาดที่ธีมของคุณใช้งานจริงหมายความว่า WordPress จะถอยไปใช้ไฟล์ต้นฉบับขนาดเต็ม — ซึ่งแย่กว่าพื้นที่ดิสก์ที่คุณประหยัดได้ และนี่หยุดแค่การสร้างไฟล์ใหม่เท่านั้น ไฟล์ที่มีอยู่แล้วจะยังคงอยู่จนกว่าคุณจะสร้างใหม่ (regenerate)
กำหนดคุณภาพ JPEG ที่ WordPress ใช้เข้ารหัสรูปที่อัปโหลดใหม่ ค่าเริ่มต้น 82
ทำงานเมื่อ
ทุกครั้งที่ WordPress เขียนไฟล์ JPEG
ซิกเนเจอร์
add_filter( 'jpeg_quality', 'my_callback', 10, 2 ); // receives $quality, $contextจุดที่ต้องระวัง
คุณภาพ 82 เหมาะกับภาพถ่าย แต่แย่อย่างเห็นได้ชัดกับภาพหน้าจอ โลโก้ และกราฟิกแบน ๆ — พวกนี้มีขอบคมและไม่มี noise แบบภาพถ่ายไว้กลบ artefact ได้ อีกอย่าง: wp_editor_set_quality เป็น filter ที่ทันสมัยกว่าและครอบคลุมคลาสตัวแก้ไขรูปภาพโดยตรง การตั้งทั้งสองตัวเป็นเรื่องปกติ
กำหนดคุณภาพเอาต์พุตที่คลาส WP_Image_Editor ใช้ (GD และ Imagick)
ทำงานเมื่อ
เมื่ออินสแตนซ์ของตัวแก้ไขรูปภาพตั้งค่าคุณภาพ
ซิกเนเจอร์
add_filter( 'wp_editor_set_quality', 'my_callback', 10, 2 ); // receives $quality, $mime_typeเพิ่มขนาดรูปภาพที่คุณกำหนดเองเข้าไปในดรอปดาวน์ขนาดในหน้าต่างสื่อ (media modal) และตัวแก้ไขบล็อก
ทำงานเมื่อ
เมื่อ UI ของสื่อสร้างตัวเลือกขนาด
ซิกเนเจอร์
add_filter( 'image_size_names_choose', 'my_callback' ); // receives $sizesตัวอย่าง
add_filter( 'image_size_names_choose', function ( $sizes ) {
return array_merge( $sizes, array( 'card' => __( 'Card', 'textdomain' ) ) );
} );จุดที่ต้องระวัง
add_image_size() ลงทะเบียนขนาดไว้ แต่ไม่ได้ทำให้มันเลือกได้ในตัวแก้ไข ทุกคำถามที่ว่า "ขนาดรูปที่ฉันกำหนดเองไม่โผล่ในดรอปดาวน์" คือการที่ filter นี้ขาดหายไป
ตรวจสอบหรือปฏิเสธไฟล์ก่อนที่มันจะถูกย้ายเข้าไปในโฟลเดอร์อัปโหลด
ทำงานเมื่อ
ระหว่างการอัปโหลด ก่อนที่ไฟล์จะถูกเขียน
ซิกเนเจอร์
add_filter( 'wp_handle_upload_prefilter', 'my_callback' ); // receives $fileจุดที่ต้องระวัง
หากต้องการปฏิเสธไฟล์ ให้ตั้งค่า $file['error'] เป็นสตริงข้อความ แล้ว return $file การ return false หรือ throw จะไม่ให้ผลอย่างที่คุณต้องการ
กรองอาร์เรย์เมตาดาต้า (รวมถึงขนาดที่ถูกสร้างขึ้น) หลังจากที่ไฟล์แนบถูกประมวลผล
ทำงานเมื่อ
หลังจากที่รูปภาพอนุพันธ์ถูกสร้างตอนอัปโหลด
ซิกเนเจอร์
add_filter( 'wp_generate_attachment_metadata', 'my_callback', 10, 2 ); // receives $metadata, $attachment_idจุดที่ต้องระวัง
นี่คือฮุกที่ปลั๊กอินปรับแต่งรูปภาพใช้กัน มันอาจช้าได้ — เพราะทำงานหลังจากที่ขนาดรูปทุกขนาดถูกเขียนเสร็จ และการเรียก HTTP ตรงนี้ทำให้การอัปโหลดทุกครั้งต้องรอมัน
กรองตัวเลือก srcset ที่ WordPress สร้างสำหรับรูปภาพแบบ responsive
ทำงานเมื่อ
เมื่อรูปภาพแบบ responsive ถูกเรนเดอร์
ซิกเนเจอร์
add_filter( 'wp_calculate_image_srcset', 'my_callback', 10, 5 );จุดที่ต้องระวัง
Removing the medium_large (768w) size elsewhere silently degrades srcset — that size exists almost entirely to serve it.
เรายังไม่ได้ตรวจสอบจำนวนอาร์กิวเมนต์ที่แน่นอนของฮุกนี้เทียบกับซอร์สโค้ดของ WordPress โปรดตรวจสอบที่ developer.wordpress.org ก่อนนำไปใช้จริง เราขอแจ้งเตือนความไม่แน่นอนไว้ดีกว่าจะนำเสนอสิ่งที่เดาเอาว่าเป็นข้อเท็จจริงแบบเงียบ ๆ
ลงทะเบียนหน้าเมนูและเมนูย่อยในหน้าแอดมิน
ทำงานเมื่อ
เมื่อเมนูแอดมินกำลังถูกสร้าง
ซิกเนเจอร์
add_action( 'admin_menu', 'my_callback' );ตัวอย่าง
add_action( 'admin_menu', function () {
add_options_page(
'My Plugin',
'My Plugin',
'manage_options', // capability — NOT a role
'my-plugin',
'my_render_settings_page'
);
} );จุดที่ต้องระวัง
อาร์กิวเมนต์ capability คือ capability ไม่ใช่ role การส่ง "administrator" ดูเหมือนจะทำงานได้ (เพราะแอดมินมี capability ชื่อนั้นในบางการตั้งค่า) แล้วก็เผลอให้สิทธิ์เข้าถึงแก่คนผิดอย่างเงียบ ๆ ให้ใช้ manage_options
พิมพ์ข้อความแจ้งเตือนที่ด้านบนของหน้าจอแอดมิน
ทำงานเมื่อ
เมื่อหน้าแอดมินถูกเรนเดอร์
ซิกเนเจอร์
add_action( 'admin_notices', 'my_callback' );จุดที่ต้องระวัง
มันทำงานบนทุกหน้าจอแอดมิน ปลั๊กอินที่แสดงข้อความ "ขอบคุณที่ติดตั้ง!" แบบไม่มีเงื่อนไขบนทุกหน้าคือแพตเทิร์นที่ถูกเกลียดที่สุดในหน้าแอดมินของ WordPress ป้องกันมันไว้ และทำให้ปิดได้
ทำงานทุกครั้งที่มีการสร้างหรืออัปเดตโพสต์ เป็นที่ปกติสำหรับบันทึกข้อมูลของ meta box
ทำงานเมื่อ
หลังจากที่โพสต์ถูกเขียนลงฐานข้อมูล
ซิกเนเจอร์
add_action( 'save_post', 'my_callback', 10, 3 ); // receives $post_id, $post, $updateตัวอย่าง
add_action( 'save_post', function ( $post_id ) {
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
if ( wp_is_post_revision( $post_id ) ) return;
if ( ! current_user_can( 'edit_post', $post_id ) ) return;
// ... now it is safe to save
}, 10, 1 );จุดที่ต้องระวัง
มันทำงานตอนบันทึกอัตโนมัติ (autosave) และตอนสร้าง revision ด้วย ไม่ใช่แค่การบันทึกจริง ๆ หากไม่มีตัวป้องกันสามตัวข้างต้น เมตาของคุณจะถูกเขียนทับด้วยค่าว่างทุกครั้งที่ตัวแก้ไขบันทึกอัตโนมัติ — บั๊กที่ดูเหมือนข้อมูลหายไปเองแบบสุ่ม ๆ
ลงทะเบียน meta box บนหน้าจอแก้ไขโพสต์
ทำงานเมื่อ
เมื่อหน้าจอแก้ไขถูกสร้าง
ซิกเนเจอร์
add_action( 'add_meta_boxes', 'my_callback', 10, 2 ); // receives $post_type, $postจุดที่ต้องระวัง
meta box แบบคลาสสิกจะไม่ปรากฏในตัวแก้ไขบล็อก เว้นแต่ตัวแก้ไขบล็อกจะถอยไปใช้โหมดความเข้ากันได้ (compatibility mode) สำหรับเว็บที่ใช้ตัวแก้ไขบล็อกโดยกำเนิด ให้ลงทะเบียน post meta ด้วย show_in_rest แล้วสร้างพาเนลแถบข้างแทน
ทำงานหลังจากที่ผู้ใช้ล็อกอินสำเร็จ
ทำงานเมื่อ
เมื่อยืนยันตัวตนสำเร็จ
ซิกเนเจอร์
add_action( 'wp_login', 'my_callback', 10, 2 ); // receives $user_login, WP_User $userทำงานทันทีหลังจากที่มีการสร้างผู้ใช้ใหม่
ทำงานเมื่อ
เมื่อมีการสมัครสมาชิก
ซิกเนเจอร์
add_action( 'user_register', 'my_callback', 10, 2 ); // receives $user_id, $userdataกรองผลลัพธ์การยืนยันตัวตน คืนค่า WP_Error เพื่อบล็อกการล็อกอิน
ทำงานเมื่อ
ระหว่างการพยายามล็อกอิน
ซิกเนเจอร์
add_filter( 'authenticate', 'my_callback', 30, 3 ); // receives $user, $username, $passwordจุดที่ต้องระวัง
priority สำคัญมากตรงนี้ คอร์ของ WordPress ผูกการตรวจสอบของตัวเองไว้ที่ priority 20 และ 30 — หากผูกเร็วเกินไป คุณจะทำงานก่อนที่รหัสผ่านจะถูกตรวจด้วยซ้ำ
ลงทะเบียน REST route และ field
ทำงานเมื่อ
เมื่อ REST API เริ่มต้นทำงาน
ซิกเนเจอร์
add_action( 'rest_api_init', 'my_callback' );ตัวอย่าง
add_action( 'rest_api_init', function () {
register_rest_route( 'myplugin/v1', '/items', array(
'methods' => 'GET',
'callback' => 'my_get_items',
'permission_callback' => '__return_true', // BE DELIBERATE ABOUT THIS
) );
} );จุดที่ต้องระวัง
permission_callback เป็นสิ่งที่จำเป็น — ตั้งแต่ WP 5.5 การละเว้นมันจะทำให้เกิด notice และการตั้งเป็น __return_true จะทำให้ endpoint เปิดสาธารณะเต็มที่ ซึ่งเหมาะกับข้อมูลที่เป็นสาธารณะจริง ๆ แต่เป็นช่องโหว่ร้ายแรงสำหรับอย่างอื่น จงตัดสินใจ อย่าปล่อยตามค่าเริ่มต้น
เพิ่มช่วงเวลาการเกิดซ้ำแบบกำหนดเองสำหรับ wp_schedule_event()
ทำงานเมื่อ
เมื่อ WordPress สร้างรายการตารางเวลาที่มีให้ใช้
ซิกเนเจอร์
add_filter( 'cron_schedules', 'my_callback' ); // receives $schedulesตัวอย่าง
add_filter( 'cron_schedules', function ( $schedules ) {
$schedules['every_five_minutes'] = array(
'interval' => 300, // seconds
'display' => __( 'Every 5 minutes', 'textdomain' ),
);
return $schedules;
} );จุดที่ต้องระวัง
WP-Cron ไม่ใช่ cron จริง มันทำงานเฉพาะเมื่อมีคนเข้าเว็บ ดังนั้นเว็บที่มีทราฟฟิกน้อยจะไม่รันตารางห้านาทีทุก ๆ ห้านาที หากเวลามีความสำคัญจริง ๆ ให้ปิด WP-Cron (DISABLE_WP_CRON) แล้วเรียก wp-cron.php จาก system cron จริง
ทำงานทันทีหลังจากที่ความคิดเห็นถูกบันทึก
ทำงานเมื่อ
เมื่อมีการส่งความคิดเห็น
ซิกเนเจอร์
add_action( 'comment_post', 'my_callback', 10, 3 ); // receives $comment_id, $approved, $commentdataกรองข้อมูลความคิดเห็นก่อนที่จะถูกบันทึก ใช้สำหรับการตรวจสแปมและการตรวจสอบความถูกต้อง
ทำงานเมื่อ
ก่อนที่ความคิดเห็นจะถูกเขียน
ซิกเนเจอร์
add_filter( 'preprocess_comment', 'my_callback' ); // receives $commentdataจุดที่ต้องระวัง
หากต้องการปฏิเสธความคิดเห็นตรงนี้ ให้เรียก wp_die() พร้อมข้อความ — การ return false ไม่ได้หยุดมัน
ทำงานบนหน้ารับคำสั่งซื้อ (order-received) หลังจากชำระเงินสำเร็จ
ทำงานเมื่อ
เมื่อลูกค้าเข้าสู่หน้าขอบคุณ (thank-you page)
ซิกเนเจอร์
add_action( 'woocommerce_thankyou', 'my_callback' ); // receives $order_idจุดที่ต้องระวัง
นี่ไม่ใช่ที่ที่เชื่อถือได้สำหรับสั่งดำเนินการจัดส่ง มันทำงานเฉพาะเมื่อลูกค้าไปถึงหน้าขอบคุณจริง ๆ — หากพวกเขาปิดแท็บหลังจ่ายเงิน มันจะไม่ทำงานเลย ให้ใช้ woocommerce_payment_complete หรือฮุกการเปลี่ยนสถานะคำสั่งซื้อสำหรับสิ่งที่ต้องเกิดขึ้นแน่ ๆ
แสดงมาร์กอัปก่อนปุ่มเพิ่มลงตะกร้าบนหน้าสินค้าทันที
ทำงานเมื่อ
ระหว่างที่หน้าสินค้าถูกเรนเดอร์
ซิกเนเจอร์
add_action( 'woocommerce_before_add_to_cart_button', 'my_callback' );เพิ่ม ลบ หรือจัดลำดับฟิลด์ใหม่บนหน้าชำระเงินแบบคลาสสิก
ทำงานเมื่อ
เมื่อฟอร์มชำระเงินถูกสร้าง
ซิกเนเจอร์
add_filter( 'woocommerce_checkout_fields', 'my_callback' ); // receives $fieldsจุดที่ต้องระวัง
มันมีผลกับหน้าชำระเงินแบบคลาสสิก (shortcode) เท่านั้น หน้าชำระเงินแบบบล็อกรุ่นใหม่จะเพิกเฉยต่อมันโดยสิ้นเชิง และปรับแต่งผ่าน Slot & Fill ใน JavaScript แทน เรื่องนี้ทำเอาเกือบทุกคนสะดุดในครั้งแรก