Передача повідомлень про помилки / попередження з мета-вікна в "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_noticesгачку для відображення (потрібно буде підключити екрани, які не встановлюються).

він робить те, що я хочу, але чи не заповнило це базу даних тоннами перехідних процесів?
onetrickpony

@One Trick Pony в нативного перехідного процесу явно видаляється (див. get_settings_errors()Джерело). Можливо, вам доведеться це зробити самостійно, якщо адаптувати логіку для сторінки, яка не налаштована.
Рарст

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');
}

Функція збереження, яку ви метабокси ви базуєте на основі необхідності:

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

насправді не працює, оскільки після збереження публікації ви переспрямовуєтесь так, що дія ніколи не запускається ...
onetrickpony

1
Куди перенаправлено? І наведений вище код, чим я користуюся, тому я знаю, що він працює.
Бейнтернет

чи підключена ваша функція збереження метабокса save_post?
onetrickpony

1
спасибі, але це робить те саме, що вказував Рарст: повідомлення про помилку зберігається у db, а потім отримується та видаляється на наступній сторінці.
onetrickpony

1
-1 для використання БД. Ви не можете гарантувати, що правильний користувач побачить помилку. Також не варто зайвих накладних витрат. Оскільки немає чіткого способу вирішення помилок метабокса, це приємна робота, але все ж неефективна. Я додав приклад того, як це роблю, у новій відповіді, щоб допомогти іншим.
Джеремі

11

Ця відповідь [ дзеркало ] від 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

Я знаю, що це питання давнє, але я знаходжу відповіді, щоб не вирішити питання.

Подовжуючи відповідь від Ана Бана, використовуючи метод Отто , я вважав, що це найкращий метод для вирішення помилок. Для цього не потрібно зберігати помилки в 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 ...
Джеремі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.