เพิ่มการตรวจสอบและการจัดการข้อผิดพลาดเมื่อบันทึกฟิลด์ที่กำหนดเองหรือไม่


27

ฉันมีฟังก์ชั่นที่กำหนดฟิลด์ที่กำหนดเองในประเภทโพสต์ สมมติว่าฟิลด์นั้นเป็น "subhead"

เมื่อบันทึกโพสต์แล้วฉันต้องการตรวจสอบความถูกต้องของอินพุตและแสดงข้อความแสดงข้อผิดพลาดบนหน้าจอแก้ไขโพสต์หากจำเป็น สิ่งที่ต้องการ:

// Handle post updating
function wpse_update_post_custom_values($post_id, $post) {

    // Do some checking...
    if($_POST['subhead'] != 'value i expect') {

        // Add an error here
        $errors->add('oops', 'There was an error.');

    }

    return $errors;

} 
add_action('save_post','wpse_update_post_custom_values',1,2);

ฉันพยายามเชื่อมโยงสิ่งนี้กับการกระทำ save_post แต่ฉันไม่สามารถหาวิธีจัดการข้อผิดพลาดได้ ดูเหมือนจะไม่มีวัตถุข้อผิดพลาดที่ส่งผ่านไปยังฟังก์ชั่นและถ้าฉันสร้าง WP_Error obj ของฉันเองและส่งคืนมันก็ไม่ได้รับความเคารพจากกลไกใด ๆ ที่แยกแยะข้อผิดพลาดในหน้าแก้ไขการโพสต์

ขณะนี้ฉันมีข้อความแสดงข้อผิดพลาดบนหน้าภายในกล่องเมตาที่กำหนดเองของฉัน แต่นี่น้อยกว่าอุดมคติ - ฉันควรมีข้อผิดพลาดขนาดใหญ่สีแดงขึ้นไปด้านบนอย่าง WP แสดงขึ้นตามปกติ

ความคิดใด ๆ

UPDATE:

จากคำตอบของ @Denis ฉันได้ลองทำหลายอย่าง การจัดเก็บข้อผิดพลาดในโลกไม่ทำงานเนื่องจาก Wordpress ทำการเปลี่ยนเส้นทางในระหว่างกระบวนการ save_post ซึ่งจะฆ่าโลกก่อนที่คุณจะสามารถแสดงได้

ฉันลงเอยเก็บไว้ในเมตาดาต้า ปัญหาเกี่ยวกับสิ่งนี้คือคุณต้องล้างพวกมันออกหรือพวกมันจะไม่หายไปเมื่อคุณนำทางไปยังหน้าอื่นดังนั้นฉันต้องเพิ่มฟังก์ชั่นอื่น ๆ ที่แนบมากับ admin_footer ที่เพิ่งกำจัดข้อผิดพลาดออกไป

ฉันไม่คาดหวังว่าการจัดการข้อผิดพลาดสำหรับบางสิ่งที่พบบ่อยมาก ฉันขาดอะไรบางอย่างที่ชัดเจนหรือเป็นวิธีที่ดีที่สุดหรือไม่

// Handle post updating
function wpse_5102_update_post_custom_values($post_id, $post) {

    // To keep the errors in
    $errors = false;

    // Do some validation...
    if($_POST['subhead'] != 'value i expect') {

        // Add an error here
        $errors .= 'whoops...there was an error.';

    }

    update_option('my_admin_errors', $errors);

    return;

} 
add_action('save_post','wpse_5102_update_post_custom_values',1,2);


// Display any errors
function wpse_5102_admin_notice_handler() {

    $errors = get_option('my_admin_errors');

    if($errors) {

        echo '<div class="error"><p>' . $errors . '</p></div>';

    }   

}
add_action( 'admin_notices', 'wpse_5102_admin_notice_handler' );


// Clear any errors
function wpse_5102__clear_errors() {

    update_option('my_admin_errors', false);

}
add_action( 'admin_footer', 'wpse_5102_clear_errors' );

คำถามที่ดี. ฉันคิดว่าคุณสามารถกำจัดadmin_footerเบ็ดถ้าคุณล้างข้อผิดพลาดในตอนท้ายของฟังก์ชั่นจัดการการแจ้งเตือนของคุณ ลดความซับซ้อนของสิ่งต่าง ๆ เพียงเล็กน้อย
Geert

คุณจะจัดการกับการเติมข้อมูลในฟิลด์แบบฟอร์มใหม่อย่างไร (ด้วยข้อมูลที่ไม่ถูกต้องที่เป็นไปได้)?
Geert

ฉันมีคำถามพื้นฐาน ไฟล์ php ของ Wordpress คืออะไร

@Karen นี่จะเป็นไฟล์ปลั๊กอินที่กำหนดเองหรือใน functions.php ของคุณ
MathSmath

ฉันอาจจะเป็นสิ่งที่เห็นได้ชัดหายไป แต่มันจะมีประสิทธิภาพมากขึ้นเล็กน้อยเพื่อให้ทำงานได้update_option('my_admin_errors', false);ทันทีหลังจากที่คำสั่งถ้าในตอนท้ายของwpse_5102_admin_notice_handler()?
Andrew Odri

คำตอบ:


6

จัดเก็บข้อผิดพลาดในชั้นเรียนของคุณหรือทั่วโลกอาจเป็นแบบชั่วคราวหรือเมตาและแสดงข้อผิดพลาดของผู้ดูแลระบบในคำขอ POST WP ไม่มีฟีเจอร์ตัวจัดการข้อความแฟลชใด ๆ


ขอบคุณที่ชี้นำฉันในทิศทางนี้! ฉันลงเอยด้วยการใช้เมตาเพื่อจัดเก็บข้อผิดพลาดเนื่องจากฉันมีปัญหาในการพยายามทำมันให้เป็นส่วนกลางหรือเป็นพร็อพเพอร์ตี้ ฉันกำลังอัปเดตคำตอบของฉันในตอนนี้เพื่ออธิบายว่าฉันทำได้อย่างไรโปรดแจ้งให้เราทราบว่านี่เป็นสิ่งที่คุณแนะนำหรือว่ามีวิธีที่ดีกว่าที่ฉันจะไม่รับ
MathSmath

ใช่นั่นเป็นเรื่องแบบนั้น อาจเก็บไว้ในตัวแปรเซสชั่นในความคิดที่สองแม้ว่า สิ่งนี้เพื่อให้ผู้เขียนหลายคนสามารถแก้ไขโพสต์ได้ในเวลาเดียวกัน :-) นอกจากนี้ฉันเชื่อว่าไม่สามารถเก็บเท็จในตัวเลือก เก็บสตริงว่างไว้แทน
เดนิสเดอเบอร์นาดี

6

ฉันขอแนะนำให้ใช้เซสชันเนื่องจากจะไม่สร้างเอฟเฟกต์แปลก ๆ เมื่อผู้ใช้สองคนแก้ไขในเวลาเดียวกัน ดังนั้นนี่คือสิ่งที่ฉันทำ:

การประชุมไม่ได้เริ่มต้นด้วย wordpress ดังนั้นคุณต้องเริ่มเซสชันในปลั๊กอินของคุณ Functions.php หรือแม้แต่ wp-config.php:

if (!session_id())
  session_start();

เมื่อบันทึกโพสต์ผนวกข้อผิดพลาดและประกาศไปยังเซสชั่น:

function my_save_post($post_id, $post) {
   if($something_went_wrong) {
     //Append error notice if something went wrong
     $_SESSION['my_admin_notices'] .= '<div class="error"><p>This or that went wrong</p></div>';
     return false; //might stop processing here
   }
   if($somthing_to_notice) {  //i.e. successful saving
     //Append notice if something went wrong
     $_SESSION['my_admin_notices'] .= '<div class="updated"><p>Post updated</p></div>';
   }

   return true;
} 
add_action('save_post','my_save_post');

พิมพ์ประกาศและข้อผิดพลาดจากนั้นทำความสะอาดข้อความในเซสชัน:

function my_admin_notices(){
  if(!empty($_SESSION['my_admin_notices'])) print  $_SESSION['my_admin_notices'];
  unset ($_SESSION['my_admin_notices']);
}
add_action( 'admin_notices', 'my_admin_notices' );

แก้ไขสำหรับรุ่นเซสชั่น: ในครั้งแรกที่ใช้ตัวแปรเซสชั่นไม่ได้ใช้ = = = ถ้าคุณเปิดการดีบักคุณสามารถตรวจสอบว่าทำไม ...

3
ฉันได้ทำเช่นนี้ แต่ถ้าคุณปล่อยปลั๊กอินให้กับผู้ชมจำนวนมากเช่นนั้นคนจะจบลงด้วยการเกลียดคุณ Wordpress ไม่ได้ยกตัวอย่างเซสชันเพราะมันถูกออกแบบมาให้ไร้สัญชาติและไม่ต้องการพวกมันและการตั้งค่าเซิร์ฟเวอร์แปลก ๆ บางอย่างจะทำให้แตก ใช้ transients API - codex.wordpress.org/Transients_APIแทนเซสชันและคุณจะรักษาความเข้ากันได้ แค่คิดว่ามันคุ้มค่าที่จะตั้งค่าเหตุผลว่าทำไมไม่ทำนี่
pospi

@pospi นี้ดูเหมือนว่าจะมีปัญหาที่คล้ายกันเช่นการใช้งานเดิมของฟังก์ชั่น get_option และ update_option ดังนั้นฉันเดาว่าทางออกจะต่อท้าย ID ผู้ใช้ปัจจุบันไปยังคีย์หรือไม่
Gazillion

ใช่ว่าจะทำงานโดยสิ้นเชิง! ตราบใดที่คุณเพิ่มบางอย่างเพื่อระบุผู้ใช้โดยเฉพาะคุณจะหลีกเลี่ยงข้อความที่ปะปนกันระหว่างผู้ใช้ที่เข้าสู่ระบบ (:
pospi

5

จากข้อเสนอแนะของpospiในการใช้งานชั่วคราวฉันได้รับสิ่งต่อไปนี้ ปัญหาเดียวคือไม่มีตะขอที่จะนำข้อความด้านล่างที่ที่ข้อความอื่นไปดังนั้นฉันจึงต้องทำการแฮ็ค jQuery เพื่อไปที่นั่นh2

ก่อนอื่นให้บันทึกข้อความแสดงข้อผิดพลาดระหว่างsave_postตัวจัดการ (หรือคล้ายกัน) ของคุณ ฉันให้อายุการใช้งานสั้น ๆ 60 วินาทีดังนั้นจึงมีระยะเวลาพอที่การเปลี่ยนเส้นทางจะเกิดขึ้น

if($has_error)
{
  set_transient( "acme_plugin_error_msg_$post_id", $error_msg, 60 );
}

จากนั้นเพียงดึงข้อความแสดงข้อผิดพลาดนั้นในหน้าถัดไปโหลดแล้วแสดง ฉันยังลบมันดังนั้นมันจะไม่ปรากฏขึ้นสองครั้ง

add_action('admin_notices', 'acme_plugin_show_messages');

function acme_plugin_show_messages()
{
  global $post;
  if ( false !== ( $msg = get_transient( "acme_plugin_error_msg_{$post->ID}" ) ) && $msg) {
    delete_transient( "acme_plugin_error_msg_{$post->ID}" );
    echo "<div id=\"acme-plugin-message\" class=\"error below-h2\"><p>$msg</p></div>";
  }
}

เนื่องจากadmin_noticesไฟไหม้ก่อนที่จะสร้างเนื้อหาของหน้าหลักการแจ้งเตือนไม่ใช่ตำแหน่งที่ข้อความการแก้ไขการโพสต์อื่นไปดังนั้นฉันจึงต้องใช้ jQuery นี้เพื่อย้ายไปที่นั่น:

jQuery('h2').after(jQuery('#acme-plugin-message'));

เนื่องจากรหัสโพสต์เป็นส่วนหนึ่งของชื่อชั่วคราวจึงควรทำงานในสภาพแวดล้อมที่มีผู้ใช้หลายคนส่วนใหญ่ยกเว้นเมื่อผู้ใช้หลายคนกำลังแก้ไขโพสต์เดียวกันพร้อมกัน


คุณช่วยอธิบายเกี่ยวกับ "เนื่องจากรหัสโพสต์เป็นส่วนหนึ่งของชื่อชั่วคราว" ได้หรือไม่? ฉันสร้างคลาสเพื่อจัดการข้อความแสดงข้อผิดพลาดโดยใช้เทคนิคนี้ แต่ฉันต้องการตัวสร้างของฉันเพื่อส่งผ่าน user_ID Transient API ใช้ user_id เมื่อทำการแฮชคีย์หรือไม่? (ฉันถามเพราะ codex ดูเหมือนจะไม่พูดถึงเรื่องนี้)
Gazillion

ไม่ แต่คุณสามารถเพิ่มได้ด้วยตนเอง acme_plugin_error_msg_POSTIDในรหัสที่ผมโพสต์ข้างต้นชื่อของชั่วคราวคือ คุณสามารถเพิ่ม ID ผู้ใช้ไปยังสิ่งที่ต้องการacme_plugin_error_msg_POSTID_USERIDได้
Joshua Coady

2

เมื่อsave_postรันจะมีการบันทึกโพสต์ไว้ในฐานข้อมูลแล้ว

มองเข้าไปในรหัสหลัก WordPress มากขึ้นโดยเฉพาะที่wp-includes/post.phpเป็นupdate_post()ฟังก์ชั่นที่มีในตัวไม่มีทางที่จะสกัดกั้นการร้องขอก่อนที่มันจะถูกบันทึกไว้ในฐานข้อมูล

อย่างไรก็ตามเราสามารถขอpre_post_updateและใช้header()และget_post_edit_link()เพื่อป้องกันการโพสต์จากการบันทึก

<?php

/**
*   Performs validation before saving/inserting custom post type
*/
function custom_post_site_save($post_id, $post_data) {
    // If this is just a revision, don't do anything.
    if (wp_is_post_revision($post_id))
        return;

    if ($post_data['post_type'] == 'my_custom_post_type') {
        // Deny post titles with less than 5 characters
        if (strlen($post_data['post_title'] < 5)) {
            header('Location: '.get_edit_post_link($post_id, 'redirect'));
            exit;
        }
    }
}
add_action( 'pre_post_update', 'custom_post_site_save', 10, 2);

หากคุณแจ้งผู้ใช้ว่ามีอะไรผิดพลาดให้ตรวจสอบส่วนสำคัญนี้: https://gist.github.com/Luc45/09f2f9d0c0e574c0285051b288a0f935


ขอบคุณสำหรับสิ่งนี้จัดการการตรวจสอบอย่างสมบูรณ์ไม่ว่าจะเผยแพร่เป็นครั้งแรกหรืออัปเดตโพสต์ คุณเพียงแค่ช่วยฉันประหยัดเวลาและความพยายาม
Zade

1

ทำไมคุณไม่ตรวจสอบสนามของคุณด้วยความช่วยเหลือของ Javascript บางส่วน? ฉันคิดว่านี่จะเป็นวิธีที่ดีที่สุดสำหรับสิ่งนี้


ขอบคุณสำหรับคำแนะนำ! สิ่งที่ฉันทิ้งไว้จากคำถาม (เพราะความเรียบง่าย) คือฉันพยายามจัดการข้อผิดพลาดในการอัปโหลดไฟล์ดังนั้นจึงต้องเป็นฝั่งเซิร์ฟเวอร์ ขอบคุณสำหรับคำแนะนำ!
MathSmath

การตรวจสอบความถูกต้องของจาวาสคริปต์ไม่ได้ป้องกันการโจมตีบางอย่างการตรวจสอบความถูกต้องฝั่งเซิร์ฟเวอร์เป็นวิธีที่ปลอดภัยเพียงอย่างเดียว นอกจากนี้ wordpress ยังมีเครื่องมือที่ดีในการตรวจสอบข้อมูลผู้ใช้ แต่ถ้าคุณตรวจสอบค่าบางอย่างก่อนส่งข้อมูลไปยังเซิร์ฟเวอร์คุณสามารถประหยัดเวลาในเซิร์ฟเวอร์ต่ำได้ ^^
nderambure

1

พยายามใช้สคริปต์ด้านบนฉันพบปัญหาแปลก ๆ สองข้อความจะปรากฏบนหน้าจอแก้ไขหลังจากการโพสต์การปรับปรุง หนึ่งกำลังแสดงสถานะของเนื้อหาจากการบันทึกก่อนหน้าและอีกอันหนึ่งจากปัจจุบัน ตัวอย่างเช่นถ้าฉันบันทึกโพสต์อย่างถูกต้องแล้วทำให้เกิดข้อผิดพลาดอันแรกคือ "ข้อผิดพลาด" และอันที่สองคือ "ตกลง" - มันสร้างขึ้นในเวลาเดียวกัน หากฉันเปลี่ยนสคริปต์และเพิ่มข้อความเดียว (เช่น "ข้อผิดพลาด") ให้เริ่มการอัปเดตหนึ่งรายการด้วย "ข้อผิดพลาด" และหลังจากนั้นอีกข้อความหนึ่งที่มีข้อความ "ตกลง" ข้อความ "ข้อผิดพลาด" จะยังคงอยู่ (ปรากฏเป็นครั้งที่สอง) ฉันต้องบันทึกด้วย "ตกลง" อีกครั้งเพื่อกำจัดมัน ฉันไม่รู้ว่ามีอะไรผิดปกติจริง ๆ ฉันได้ทำการทดสอบในเซิร์ฟเวอร์ภายในสามแห่งและมีปัญหาเดียวกันกับแต่ละเซิร์ฟเวอร์


ฉันทำการทดสอบเพิ่มเติมของสคริปต์ที่ง่ายกว่ารุ่นที่สองซึ่งฉันได้กล่าวถึงข้างต้นและดูเหมือนว่าถ้าข้อความ "ข้อผิดพลาด" ถูกผนวกเข้ากับอาร์เรย์ของเซสชันจริงๆจะปรากฏบนหน้าจอแก้ไข หากไม่มีข้อความ (ทุกอย่างเป็น "ok") และข้อความก่อนหน้านี้เป็นข้อผิดพลาดจะปรากฏขึ้นบนหน้าจอ มีอะไรแปลก ๆ มันถูกสร้างขึ้นในเวลาของการบันทึก (ไม่แคช) - ฉันได้ตรวจสอบโดยใช้วันที่ () ในเนื้อหาของข้อความแสดงข้อผิดพลาด ตอนนี้ฉันสับสนอย่างสิ้นเชิง
jlub

ตกลงในกรณีที่คนอื่นกำลังดึงผมออกจากหัวของเขา - ปรากฎว่าระบบการแก้ไข Wordpress เป็นปัญหา (ข้อผิดพลาดบางประเภทอาจ?) ฉันปิดการใช้งานและตอนนี้ทุกอย่างก็โอเค

0

ฉันเขียนปลั๊กอินที่เพิ่มในการจัดการข้อผิดพลาดแบบแฟลชสำหรับหน้าจอแก้ไขการโพสต์และป้องกันไม่ให้มีการเผยแพร่โพสต์จนกว่าจะกรอกฟิลด์ที่ต้องการ:

https://github.com/interconnectit/required-fields

อนุญาตให้คุณสร้างฟิลด์การโพสต์ใด ๆ ที่จำเป็น แต่คุณสามารถใช้ API ที่มีให้เพื่อสร้างฟิลด์ที่กำหนดเองใด ๆ ที่ต้องการด้วยข้อความแสดงข้อผิดพลาดที่ปรับแต่งได้และฟังก์ชันการตรวจสอบ มันเป็นค่าเริ่มต้นในการตรวจสอบว่าเขตข้อมูลว่างเปล่าหรือไม่


อย่าลังเลที่จะเพิ่มปัญหาใด ๆ ใน GitHub ถ้าคุณเจอพวกเขา ฉันต้องจัดทำเอกสาร API ให้ดีขึ้นเช่นกันเนื่องจากมีตัวกรอง adiditional ที่คุณสามารถใช้ได้
sanchothefat
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.