การส่งข้อความข้อผิดพลาด / คำเตือนจากกล่องเมตาไปที่“ admin_notices”


20

ฉันมีเมตาบ็อกซ์ธรรมดาที่อัปเดตฟิลด์โพสต์ที่กำหนดเอง (โดยใช้update_post_meta())

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

คำตอบ:


9

คุณสามารถทำได้ด้วยมือ แต่ WP ก็ทำเช่นนี้เพื่อการตั้งค่าข้อผิดพลาด:

  1. add_settings_error() เพื่อสร้างข้อความ
  2. แล้วก็ set_transient('settings_errors', get_settings_errors(), 30);
  3. settings_errors()ในadmin_noticeshook เพื่อแสดง (จะต้องขอสำหรับหน้าจอที่ไม่ได้ตั้งค่า)

มันเป็นสิ่งที่ฉันต้องการ แต่สิ่งนี้จะไม่เติมฐานข้อมูลด้วยทรานแซคชั่นมากมายใช่ไหม
onetrickpony

@One Trick Pony ในกระบวนการดั้งเดิมชั่วคราวจะถูกลบออกอย่างชัดเจน (ดูget_settings_errors()แหล่งที่มา) คุณอาจต้องทำด้วยตัวเองหากปรับตรรกะสำหรับหน้าที่ไม่ได้ตั้งค่า
Rarst

2
ยังฉันไม่ชอบความคิดในการจัดเก็บข้อความผิดพลาดชั่วคราวใน db ฉันจะใช้ ajax เพื่อเตือนผู้ใช้เกี่ยวกับการเปลี่ยนอินพุต
onetrickpony

ด้วยการแคชวัตถุความยุ่งเหยิงของฐานข้อมูลจะไม่เป็นปัญหา
lkraav

15

คุณสามารถใช้admin_noticesเบ็ด

ก่อนกำหนดฟังก์ชั่นแจ้งให้ทราบล่วงหน้า:

function my_admin_notice(){
    //print the message
    echo '<div id="message">
       <p>metabox as errors on save message here!!!</p>
    </div>';
    //make sure to remove notice after its displayed so its only displayed when needed.
    remove_action('admin_notices', 'my_admin_notice');
}

คุณใช้ฟังก์ชั่นการบันทึก metabox ของคุณถ้าจำเป็นเพิ่ม:

...
...
if($errors){
    add_action('admin_notices', 'my_admin_notice');
}
...
...

ปรับปรุง

อย่างที่ฉันสัญญาไว้ที่นี่เป็นตัวอย่างหนึ่งของวิธีที่ฉันเพิ่มข้อความแสดงข้อผิดพลาดจากเมท็อกซ์ของฉัน

<?php
/*
Plugin Name: one-trick-pony-notice
Plugin URI: http://en.bainternet.info
Description: Just to proof a point using admin notice form metabox
Version: 1.0
Author: Bainternet
Author URI: http://en.bainternet.info
*/

/*  admin notice */
function my_admin_notice(){
    //print the message
    global $post;
    $notice = get_option('otp_notice');
    if (empty($notice)) return '';
    foreach($notice as $pid => $m){
        if ($post->ID == $pid ){
            echo '<div id="message" class="error"><p>'.$m.'</p></div>';
            //make sure to remove notice after its displayed so its only displayed when needed.
            unset($notice[$pid]);
            update_option('otp_notice',$notice);
            break;
        }
    }
}

//hooks

add_action('add_meta_boxes', 'OT_mt_add');
add_action('save_post', 'OT_mt_save');
add_action('admin_notices', 'my_admin_notice',0);

//add metabox
function OT_mt_add() {
    add_meta_box('OT_mt_sectionid', __( 'One Trick Meta Box notice', 'textdomain' ),'OT_mt_display','post');
}

//display metabox
function OT_mt_display() {

  // Use nonce for verification
  wp_nonce_field( plugin_basename(__FILE__), 'myplugin_noncename' );

  // The actual fields for data entry
  echo '<label for="myplugin_new_field">';
       _e("leave blank to get a notice on publish or update", 'textdomain' );
  echo '</label> ';
  echo '<input type="text" id="ot_field" name="ot_field" value="" size="25" />';

}


//save metabox here is were i check the fields and if empty i display a message
function OT_mt_save( $post_id ) {

  // verify this came from the our screen and with proper authorization,
  // because save_post can be triggered at other times
    if (!isset($_POST['myplugin_noncename'])) return $post_id;
  if ( !wp_verify_nonce( $_POST['myplugin_noncename'], plugin_basename(__FILE__) ) )
      return $post_id;

  // verify if this is an auto save routine. 
  // If it is our form has not been submitted, so we dont want to do anything
  if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) 
      return $post_id;


  if(!isset($_POST['ot_field']) || empty($_POST['ot_field'])){
    //field left empty so we add a notice
    $notice = get_option('otp_notice');
    $notice[$post_id] = "You have left the field empty";
    update_option('otp_notice',$notice);
  }

}

ตอนนี้เมื่อมองหารหัสนี้ฉันก็พบว่าวิธีการเดิม ๆ ของฉันทำได้โดยใช้post_updated_messagesfilter hook ในลักษณะเดียวกันดังนั้นฉันจะเพิ่มมันด้วย:

<?php
/*
Plugin Name: one-trick-pony-notice2
Plugin URI: http://en.bainternet.info
Description: just like the one above but this time using post_updated_messages hook
Version: 1.0
Author: Bainternet
Author URI: http://en.bainternet.info
*/

//hooks
add_filter('post_updated_messages','my_messages',0);
add_action('add_meta_boxes', 'OT_mt_add');
add_action('save_post', 'OT_mt_save');


//add metabox
function OT_mt_add() {
    add_meta_box('OT_mt_sectionid', __( 'One Trick Meta Box notice', 'textdomain' ),'OT_mt_display','post');
}

//display metabox
function OT_mt_display() {

  // Use nonce for verification
  wp_nonce_field( plugin_basename(__FILE__), 'myplugin_noncename' );

  // The actual fields for data entry
  echo '<label for="myplugin_new_field">';
       _e("leave blank to get a notice on publish or update", 'textdomain' );
  echo '</label> ';
  echo '<input type="text" id="ot_field" name="ot_field" value="" size="25" />';

}


//save metabox here is were i check the fields and if empty i display a message
function OT_mt_save( $post_id ) {

  // verify this came from the our screen and with proper authorization,
  // because save_post can be triggered at other times
    if (!isset($_POST['myplugin_noncename'])) return $post_id;
  if ( !wp_verify_nonce( $_POST['myplugin_noncename'], plugin_basename(__FILE__) ) )
      return $post_id;

  // verify if this is an auto save routine. 
  // If it is our form has not been submitted, so we dont want to do anything
  if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) 
      return $post_id;


  if(!isset($_POST['ot_field']) || empty($_POST['ot_field'])){
    //field left empty so we add a notice
    $notice = get_option('otp_notice');
    $notice[$post_id] = "You have left the field empty";
    update_option('otp_notice',$notice);
  }

}

//messages filter
function my_messages($m){
    global $post;
    $notice = get_option('otp_notice');
    if (empty($notice)) return $m;
    foreach($notice as $pid => $mm){
        if ($post->ID == $pid ){
            foreach ($m['post'] as $i => $message){
                $m['post'][$i] = $message.'<p>'.$mm.'</p>';

            }
            unset($notice[$pid]);
            update_option('otp_notice',$notice);
            break;
        }
    }
    return $m;
}

ไม่ได้ผลจริงๆเพราะหลังจากที่คุณบันทึกโพสต์คุณจะถูกเปลี่ยนเส้นทางเพื่อให้การกระทำที่ไม่เคยทำงาน ...
onetrickpony

1
เปลี่ยนเส้นทางอยู่ที่ไหน และรหัสข้างต้นคือสิ่งที่ฉันใช้ดังนั้นฉันรู้ว่ามันใช้งานได้
Bainternet

ฟังก์ชั่นการบันทึก metabox ของคุณติดอยู่save_postหรือไม่?
onetrickpony

1
ขอบคุณ แต่นี่ทำสิ่งเดียวกับ Rarst ที่ชี้: ข้อความแสดงข้อผิดพลาดจะถูกบันทึกไว้ใน db แล้วดึงและลบออกในหน้าถัดไป
onetrickpony

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

11

คำตอบ [ mirror ]จาก Otto ใน WP Tavern แก้ปัญหาชั่วคราวด้วยการทำสิ่งที่ WordPress ทำเพื่อแก้ไขปัญหาการเปลี่ยนเส้นทาง ทำงานให้ฉันโดยสิ้นเชิง

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

WordPress ทำเช่นนี้โดยส่งพารามิเตอร์ข้อความใน URL หมายเลขข้อความแสดงถึงข้อความที่จะแสดง

คุณสามารถทำสิ่งเดียวกันได้โดยขอredirect_post_locationตัวกรองแล้วใช้add_query_argเพื่อเพิ่มพารามิเตอร์ของคุณเองในคำขอ ชอบมาก

add_filter('redirect_post_location','my_message');
function my_message($loc) {
 return add_query_arg( 'my_message', 123, $loc );
}

สิ่งนี้จะเพิ่มmy_message=123ในแบบสอบถาม จากนั้นหลังจากเปลี่ยนเส้นทางคุณสามารถตรวจสอบการตั้งค่า my_message ใน$_GETและแสดงข้อความที่เหมาะสมตามลำดับ


3

ฉันรู้ว่าคำถามนี้เก่า แต่ฉันพบคำตอบที่นี่เพื่อไม่แก้ปัญหา

เมื่อขยายคำตอบออกจาก Ana Ban โดยใช้วิธีของ Ottoฉันพบว่านี่เป็นวิธีที่ดีที่สุดในการจัดการข้อผิดพลาด สิ่งนี้ไม่ต้องการการจัดเก็บข้อผิดพลาดใน db

ฉันรวมวัตถุ Metabox ที่ฉันใช้ สิ่งนี้ทำให้ฉันสามารถเพิ่มข้อความแสดงข้อผิดพลาดใหม่ได้อย่างง่ายดายและมั่นใจว่าผู้ใช้ที่ถูกต้องเห็นข้อความแสดงข้อผิดพลาด (ใช้ db นี่ไม่ใช่การรับประกัน)

<?php
/**
 * Class MetaboxExample
 */
class MetaboxExample {

    /**
     * Defines the whitelist for allowed screens (post_types)
     */
    private $_allowedScreens = array( 'SCREENS_TO_ALLOW_METABOX' );

    /**
     * Get parameter for the error box error code
     */
    const GET_METABOX_ERROR_PARAM = 'meta-error';

    /**
     * Defines admin hooks
     */
    public function __construct() {
        add_action('add_meta_boxes', array($this, 'addMetabox'), 50);
        add_action('save_post', array($this, 'saveMetabox'), 50);
        add_action('edit_form_top', array($this, 'adminNotices')); // NOTE: admin_notices doesn't position this right on custom post type pages, haven't testes this on POST or PAGE but I don't see this an issue
    }

    /**
     * Adds the metabox to specified post types
     */
    public function addMetabox() {
        foreach ( $this->_allowedScreens as $screen ) {
            add_meta_box(
                'PLUGIN_METABOX',
                __( 'TITLE', 'text_domain' ),
                array($this, 'metaBox'),
                $screen,
                'side',
                'high'
            );
        }
    }

    /**
     * Output metabox content
     * @param $post
     */
    public function metaBox($post) {
        // Add an nonce field so we can check for it later.
        wp_nonce_field( 'metaboxnonce', 'metaboxnonce' );
        // Load meta data for this metabox
        $someValue = get_post_meta( $post->ID, 'META_KEY_IDENTIFIER', true );
        ?>
        <p>
            <label for="some-value" style="width: 120px; display: inline-block;">
                <?php _e( 'Some Field:', 'text_domain' ); ?>
            </label>
            &nbsp;
            <input type="text" id="some-value" name="some_value" value="<?php esc_attr_e( $someValue ); ?>" size="25" />
        </p>
    <?php
    }

    /**
     * Save method for the metabox
     * @param $post_id
     */
    public function saveMetabox($post_id) {
        global $wpdb;

        // Check if our nonce is set.
        if ( ! isset( $_POST['metaboxnonce'] ) ) {
            return $post_id;
        }
        // Verify that the nonce is valid.
        if ( ! wp_verify_nonce( $_POST['metaboxnonce'], 'metaboxnonce' ) ) {
            return $post_id;
        }
        // If this is an autosave, our form has not been submitted, so we don't want to do anything.
        if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
            return $post_id;
        }
        // Check the user's permissions.
        if ( isset( $_POST['post_type'] ) && 'page' == $_POST['post_type'] ) {
            if ( ! current_user_can( 'edit_page', $post_id ) ) {
                return $post_id;
            }
        } else {
            if ( ! current_user_can( 'edit_post', $post_id ) ) {
                return $post_id;
            }
        }
        // Make sure that it is set.
        if ( !isset( $_POST['some_value'] ) ) {
            return $post_id;
        }
        // Sanitize user input.
        $someValue = sanitize_text_field( $_POST['some_value'] );
        // Check to make sure there is a value
        if (empty($someValue)) {
            // Add our error code
            add_filter('redirect_post_location', function($loc) {
                return add_query_arg( self::GET_METABOX_ERROR_PARAM, 1, $loc );
            });
            return $post_id; // make sure to return so we don't allow further processing
        }
        // Update the meta field in the database.
        update_post_meta( $post_id, 'META_KEY_IDENTIFIER', $someValue );
    }

    /**
     * Metabox admin notices
     */
    public function adminNotices() {
        if (isset($_GET[self::GET_METABOX_ERROR_PARAM])) {
            $screen = get_current_screen();
            // Make sure we are in the proper post type
            if (in_array($screen->post_type, $this->_allowedScreens)) {
                $errorCode = (int) $_GET[self::GET_METABOX_ERROR_PARAM];
                switch($errorCode) {
                    case 1:
                        $this->_showAdminNotice( __('Some error happened', 'text_domain') );
                        break;
                    // More error codes go here for outputting errors
                }
            }
        }
    }

    /**
     * Shows the admin notice for the metabox
     * @param $message
     * @param string $type
     */
    private function _showAdminNotice($message, $type='error') {
        ?>
        <div class="<?php esc_attr_e($type); ?> below-h2">
            <p><?php echo $message; ?></p>
        </div>
    <?php
    }

}

ปัญหาเดียวที่ฉันมีกับคำตอบนี้คือมันไม่ทำงานกับ PHP 5.2 ฉันไม่ได้บอกว่าเราทุกคนควรสนับสนุน HPP 5.2 แต่จนกระทั่ง WordPress มี PHP 5.2 เป็นข้อกำหนดขั้นต่ำที่เราต้องสนับสนุนหากเราแจกจ่ายปลั๊กอิน :(
Sudar

1
หากคุณลบฟังก์ชั่นที่ไม่ระบุชื่อออกและทำให้เป็นวิธีสาธารณะมันก็ใช้ได้ดี ฉันเข้าใจปัญหาของคุณ แต่โดยส่วนตัวฉันจะไม่พัฒนาสำหรับรุ่น EOL ของ PHP ( php.net/eol.php ) 5.2 EOL คือ 6 มกราคม 2011 WordPress ควรใช้ความพยายามมากกว่าที่จะไม่รองรับรุ่น EOL แต่นั่นเป็นอีกเรื่องหนึ่ง รวมถึง บริษัท โฮสติ้งที่ไม่ดีหลายแห่งที่ยังคงให้บริการเวอร์ชัน EOL ...
Jeremy
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.