Passaggio di messaggi di errore / avviso da una meta-casella a "admin_notices"


20

Ho una semplice meta-box che aggiorna i campi personalizzati post (usando update_post_meta()).

Come posso inviare un messaggio di errore o di avviso alla pagina successiva dopo che l'utente pubblica / aggiorna il post e non riempie uno dei campi della meta-box (o li riempie con dati non validi)?

Risposte:


9

Puoi farlo a mano, ma WP lo fa nativamente in questo modo per errori di impostazione:

  1. add_settings_error() per creare un messaggio.
  2. Poi set_transient('settings_errors', get_settings_errors(), 30);
  3. settings_errors()in admin_noticesgancio a display (dovrà agganciare ai non-settings copie).

fa quello che voglio, ma questo non riempirebbe il database di tonnellate di transitori?
onetrickpony,

@One Trick Pony nel transitorio del processo nativo viene eliminato esplicitamente (vedi get_settings_errors()sorgente). Potrebbe essere necessario farlo da soli se si adatta la logica per la pagina senza impostazioni.
Rarst

2
ancora non mi piace l'idea di memorizzare messaggi di errore temporanei nel db.
Userò Ajax

Con la memorizzazione nella cache degli oggetti, il disordine del database non sarebbe un problema.
lkraav,

15

puoi usare il admin_noticesgancio

per prima cosa definire la funzione di avviso:

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

La funzione di salvataggio di te metabox basata sull'eventuale aggiunta aggiunge:

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

Aggiornare

Come ho promesso, ecco un esempio di come aggiungo un messaggio di errore dal mio metabox

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

}

Ora, cercando questo codice, ho trovato il mio vecchio modo di farlo usando l' post_updated_messageshook del filtro allo stesso modo, quindi lo aggiungerò anch'io:

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

non funziona davvero perché dopo aver salvato il post, verrai reindirizzato in modo che l'azione non
venga

1
Reindirizzato dove? E il codice sopra è quello che uso, quindi so che funziona.
Bainternet,

la funzione di salvataggio di metabox è agganciata save_post?
onetrickpony,

1
grazie, ma questo fa la stessa cosa che ha indicato Rarst: il messaggio di errore viene salvato nel db, quindi recuperato ed eliminato nella pagina successiva.
onetrickpony,

1
-1 per l'utilizzo di un DB. Non è possibile garantire che l'utente corretto vedrà l'errore. Inoltre, non vale il sovraccarico inutile. Per non avere un modo chiaro di gestire gli errori di metabox, questo è un bel lavoro a tutto tondo ma ancora non efficiente. Ho aggiunto un esempio del modo in cui lo faccio in una nuova risposta per aiutare gli altri.
Jeremy,

11

Questa risposta [ mirror ] di Otto in WP Tavern, in realtà risolve il problema temporaneo facendo ciò che WordPress stesso fa per superare il problema di reindirizzamento. Ha funzionato totalmente per me.

Il problema è che i transitori sono lì per tutti. Se hai più di un utente che fa cose contemporaneamente, il messaggio di errore può andare alla persona sbagliata. È una condizione di gara.

WordPress lo fa effettivamente passando un parametro di messaggio nell'URL. Il numero del messaggio indica quale messaggio visualizzare.

Puoi fare lo stesso agganciando il redirect_post_locationfiltro e quindi usando add_query_argper aggiungere il tuo parametro alla richiesta. Così:

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

Questo aggiunge my_message=123alla query. Quindi, dopo il reindirizzamento, è possibile rilevare l'impostazione my_message in $_GETe visualizzare il messaggio corretto di conseguenza.


3

So che questa domanda è vecchia ma trovo qui le risposte per non risolvere il problema.

Estendendo la risposta di Ana Ban, usando il metodo Otto , ho scoperto che questo è il metodo migliore per gestire gli errori. Ciò non richiede la memorizzazione degli errori nel db.

Ho incluso una versione ridotta di un oggetto Metabox che uso. Ciò mi consente di aggiungere facilmente nuovi messaggi di errore e di garantire che l'utente corretto visualizzi il messaggio di errore (utilizzando il db, questa non è una garanzia).

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

}

L'unico problema che ho con questa risposta è che non funziona con PHP 5.2. Non sto dicendo che dovremmo tutti supportare HPP 5.2, ma fino a quando WordPress non avrà PHP 5.2 come requisito minimo, dovremo supportarlo se stiamo distribuendo il plugin :(
Sudar,

1
Se hai rimosso la funzione anonima e la rendi un metodo pubblico, dovrebbe funzionare correttamente. Capisco il tuo problema ma personalmente non svilupperò una versione EOL di PHP ( php.net/eol.php ) 5.2 EOL era il 6 gennaio 2011. WordPress dovrebbe fare uno sforzo maggiore per non supportare le versioni EOL ma questa è un'altra storia più molte cattive società di hosting che ancora fornivano versioni EOL ...
Jeremy,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.