将错误/警告消息从元框传递到“admin_Notitions”

时间:2011-04-21 作者:onetrickpony

我有一个简单的元框,可以更新post自定义字段(使用update_post_meta()).

在用户发布/更新帖子并且没有填充其中一个元框字段(或用无效数据填充)后,我如何向下一页发送错误或警告消息?

4 个回复
最合适的回答,由SO网友:Rarst 整理而成

您可以手动执行此操作,但WP在设置错误时会这样做:

  1. add_settings_error() 创建消息set_transient(\'settings_errors\', get_settings_errors(), 30);
  2. settings_errors() 在里面admin_notices 挂钩显示(需要挂钩非设置屏幕)

SO网友:Bainternet

您可以使用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_messages 过滤钩子的方式大致相同,因此我也要添加:

<?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;
}

SO网友:Ana Ban

This answer [mirror]实际上通过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 到查询。然后,在重定向之后,您可以在$_GET 并相应地显示正确的消息。

SO网友:Jeremy

我知道这个问题由来已久,但我在这里找到的答案并不能解决这个问题。

扩展Ana Ban的答案,使用Otto\'s method, 我发现这是处理错误的最佳方法。这不需要将错误存储在数据库中。

我包括了我使用的元盒对象的精简版本。这允许我轻松添加新的错误消息,并确保正确的用户看到错误消息(使用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
    }

}

结束

相关推荐

无法在自定义构建的Metabox中保存自定义分类术语

我大致遵循了tutorial here 关于如何创建“自定义分类输入面板”。我正在使用自定义帖子类型homes 还有一种自定义分类法beds (用于记录一所房子的床位数)。我已经在下拉菜单中显示了分类术语,但无法在保存帖子时保存它们。我开始只是发布旨在保存术语的代码,但意识到我应该发布创建和显示元盒的代码,以用于上下文。自定义帖子类型名称为“homes”,自定义分类名称为“beds”。分类法是分层的(我认为这并不重要,但我可能错了)。//adding metaboxes for the homes pos