Transmiterea mesajelor de eroare/avertisment de la o meta box la "admin_notices"

21 apr. 2011, 22:48:59
Vizualizări: 14.2K
Voturi: 22

Am o meta box simplă care actualizează câmpurile personalizate ale postării (folosind update_post_meta()).

Cum pot trimite un mesaj de eroare sau avertisment către pagina următoare după ce utilizatorul publică/actualizează postarea și nu completează unul dintre câmpurile meta box (sau le completează cu date invalide)?

0
Toate răspunsurile la întrebare 4
13
16

poți folosi hook-ul admin_notices

mai întâi definește funcția pentru notificare:

function my_admin_notice(){
    //afișează mesajul
    echo '<div id="message">
       <p>metabox ca erori la salvarea mesajului aici!!!</p>
    </div>';
    //asigură-te că elimini notificarea după afișare, astfel încât să fie afișată doar când este necesar.
    remove_action('admin_notices', 'my_admin_notice');
}

Apoi în funcția de salvare a metabox-ului, în funcție de nevoie, adaugă:

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

Actualizare

După cum am promis, iată un exemplu despre cum adaug un mesaj de eroare pentru metabox-ul meu

<?php
/*
Plugin Name: one-trick-pony-notice
Plugin URI: http://en.bainternet.info
Description: Doar pentru a demonstra un punct folosind notificarea admin din metabox
Version: 1.0
Author: Bainternet
Author URI: http://en.bainternet.info
*/

/*  notificare admin */
function my_admin_notice(){
    //afișează mesajul
    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>';
            //asigură-te că elimini notificarea după afișare, astfel încât să fie afișată doar când este necesar.
            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);

//adaugă metabox
function OT_mt_add() {
    add_meta_box('OT_mt_sectionid', __( 'Notificare Metabox One Trick', 'textdomain' ),'OT_mt_display','post');
}

//afișează metabox
function OT_mt_display() {

  // Folosește nonce pentru verificare
  wp_nonce_field( plugin_basename(__FILE__), 'myplugin_noncename' );

  // Câmpurile efective pentru introducerea datelor
  echo '<label for="myplugin_new_field">';
       _e("lasă gol pentru a primi o notificare la publicare sau actualizare", 'textdomain' );
  echo '</label> ';
  echo '<input type="text" id="ot_field" name="ot_field" value="" size="25" />';

}


//salvează metabox - aici verific câmpurile și dacă sunt goale afișez un mesaj
function OT_mt_save( $post_id ) {

  // verifică dacă aceasta provine din ecranul nostru și cu autorizația corespunzătoare,
  // deoarece save_post poate fi declanșat în alte momente
    if (!isset($_POST['myplugin_noncename'])) return $post_id;
  if ( !wp_verify_nonce( $_POST['myplugin_noncename'], plugin_basename(__FILE__) ) )
      return $post_id;

  // verifică dacă aceasta este o rutină de salvare automată. 
  // Dacă este, formularul nostru nu a fost trimis, așa că nu vrem să facem nimic
  if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) 
      return $post_id;


  if(!isset($_POST['ot_field']) || empty($_POST['ot_field'])){
    //câmp lăsat gol, așa că adăugăm o notificare
    $notice = get_option('otp_notice');
    $notice[$post_id] = "Ai lăsat câmpul gol";
    update_option('otp_notice',$notice);
  }

}

Acum, când am căutat acest cod, am găsit vechiul meu mod de a face acest lucru folosind hook-ul de filtru post_updated_messages în aproximativ același mod, așa că voi adăuga și asta:

<?php
/*
Plugin Name: one-trick-pony-notice2
Plugin URI: http://en.bainternet.info
Description: la fel ca cel de mai sus, dar de data aceasta folosind hook-ul post_updated_messages
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');


//adaugă metabox
function OT_mt_add() {
    add_meta_box('OT_mt_sectionid', __( 'Notificare Metabox One Trick', 'textdomain' ),'OT_mt_display','post');
}

//afișează metabox
function OT_mt_display() {

  // Folosește nonce pentru verificare
  wp_nonce_field( plugin_basename(__FILE__), 'myplugin_noncename' );

  // Câmpurile efective pentru introducerea datelor
  echo '<label for="myplugin_new_field">';
       _e("lasă gol pentru a primi o notificare la publicare sau actualizare", 'textdomain' );
  echo '</label> ';
  echo '<input type="text" id="ot_field" name="ot_field" value="" size="25" />';

}


//salvează metabox - aici verific câmpurile și dacă sunt goale afișez un mesaj
function OT_mt_save( $post_id ) {

  // verifică dacă aceasta provine din ecranul nostru și cu autorizația corespunzătoare,
  // deoarece save_post poate fi declanșat în alte momente
    if (!isset($_POST['myplugin_noncename'])) return $post_id;
  if ( !wp_verify_nonce( $_POST['myplugin_noncename'], plugin_basename(__FILE__) ) )
      return $post_id;

  // verifică dacă aceasta este o rutină de salvare automată. 
  // Dacă este, formularul nostru nu a fost trimis, așa că nu vrem să facem nimic
  if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) 
      return $post_id;


  if(!isset($_POST['ot_field']) || empty($_POST['ot_field'])){
    //câmp lăsat gol, așa că adăugăm o notificare
    $notice = get_option('otp_notice');
    $notice[$post_id] = "Ai lăsat câmpul gol";
    update_option('otp_notice',$notice);
  }

}

//filtru de mesaje
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;
}
21 apr. 2011 23:02:08
Comentarii

nu funcționează cu adevărat pentru că după ce salvezi postarea, ești redirecționat astfel încât acea acțiune nu se execută niciodată...

onetrickpony onetrickpony
23 apr. 2011 00:16:17

Redirecționat unde? Și codul de mai sus este ceea ce folosesc eu, așa că știu că funcționează.

Bainternet Bainternet
23 apr. 2011 00:23:13

funcția ta de salvare a metabox-ului este conectată la save_post?

onetrickpony onetrickpony
23 apr. 2011 00:31:00

save_post sau wp_insert_post_data de ce?

Bainternet Bainternet
23 apr. 2011 00:34:54

pentru că nu funcționează :) După ce apeși butonul de publicare, postarea este salvată și apoi ești redirecționat înapoi la pagina de editare.

onetrickpony onetrickpony
23 apr. 2011 00:43:10

M-ai făcut să mă îngrijorez pentru un minut, notificarea este afișată pe ecranul de editare și funcționează perfect.

Bainternet Bainternet
23 apr. 2011 15:47:08

poți posta codul pe care îl folosești, metabox-ul și toate cele? Pentru că am încercat codul tău de mai sus și nu văd nicio notificare venind din meta box-ul meu...

onetrickpony onetrickpony
23 apr. 2011 17:16:12

Sigur, imediat ce ajung acasă o să postez codul meu.

Bainternet Bainternet
23 apr. 2011 17:43:15

@One Trick Pony: verifică plugin-urile pe care ți le-am postat.

Bainternet Bainternet
24 apr. 2011 04:39:56

mers, dar acesta face același lucru precum a indicat Rarst: mesajul de eroare este salvat în baza de date, apoi preluat și șters pe pagina următoare.

onetrickpony onetrickpony
25 apr. 2011 14:56:41

@One Trick Pony: da, salvează în baza de date, dar este o opțiune frumoasă (doar un rând în baza de date) și este șters automat când folosești codul de mai sus, așa că nu trebuie să-ți faci griji că baza de date se va umple cu tranziții.

Bainternet Bainternet
26 apr. 2011 14:24:18

-1 pentru utilizarea unei baze de date. Nu poți garanta că utilizatorul corect va vedea eroarea. De asemenea, nu merită overhead-ul inutil. Pentru lipsa unei metode clare de gestionare a erorilor metabox, aceasta este o soluție temporară bună, dar încă ineficientă. Am adăugat un exemplu despre cum abordez eu acest lucru într-un răspuns nou pentru a ajuta pe alții.

Jeremy Jeremy
12 feb. 2015 17:32:13

Aș adăuga if (empty($post)) return ''; înainte de if (empty($notice)) return ''; altfel va afișa erori pe întregul site, mai ales dacă nu conțin informația $post.

soniccool soniccool
12 feb. 2020 22:34:27
Arată celelalte 8 comentarii
0
11

Acest răspuns [oglindă] de la Otto în WP Tavern, rezolvă de fapt problema tranzientelor făcând ceea ce face WordPress însuși pentru a depăși problema redirecționării. A funcționat perfect pentru mine.

Problema este că tranzientele sunt disponibile pentru toată lumea. Dacă ai mai mult de un utilizator care efectuează acțiuni în același timp, mesajul de eroare poate ajunge la persoana greșită. Este o condiție de concurență.

WordPress rezolvă acest lucru prin transmiterea unui parametru de mesaj în URL. Numărul mesajului indică care mesaj să fie afișat.

Poți face același lucru prin conectarea la filtrul redirect_post_location și apoi folosind add_query_arg pentru a adăuga propriul parametru la cerere. Ca în exemplul de mai jos:

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

Aceasta adaugă mesajul_meu=123 la interogare. Apoi, după redirecționare, poți detecta setarea mesajul_meu în $_GET și afișa mesajul corespunzător.

14 mai 2012 11:27:11
4
10

Puteți face asta manual, dar WordPress face asta în mod nativ pentru erorile de setări:

  1. add_settings_error() pentru a crea mesajul.
  2. Apoi set_transient('settings_errors', get_settings_errors(), 30);
  3. settings_errors() în hook-ul admin_notices pentru afișare (va trebui să folosiți hook-ul pentru ecranele care nu sunt de setări).
21 apr. 2011 23:04:16
Comentarii

face ce vreau eu, dar nu ar umple asta baza de date cu o grămadă de transient-uri?

onetrickpony onetrickpony
23 apr. 2011 00:14:58

@One Trick Pony în procesul nativ transient-ul este șters explicit (vezi codul sursă get_settings_errors()). Poate fi necesar să faci asta manual dacă adaptezi logica pentru o pagină non-settings.

Rarst Rarst
23 apr. 2011 00:20:48

totuși nu-mi place ideea de a stoca mesaje de eroare temporare în baza de date. voi folosi ajax pentru a avertiza utilizatorul la schimbarea input-ului

onetrickpony onetrickpony
23 apr. 2011 00:23:02

Cu caching-ul pe obiecte, aglomerarea bazei de date nu ar fi o problemă.

lkraav lkraav
3 oct. 2017 15:16:37
2

Știu că această întrebare este veche, dar consider că răspunsurile de aici nu rezolvă problema.

Extinzând răspunsul de la Ana Ban, folosind metoda lui Otto, am constatat că aceasta este cea mai bună metodă pentru gestionarea erorilor. Aceasta nu necesită stocarea erorilor în baza de date.

Am inclus o versiune simplificată a unui obiect Metabox pe care îl folosesc. Acest lucru îmi permite să adaug cu ușurință noi mesaje de eroare și să mă asigur că utilizatorul corect vede mesajul de eroare (folosind baza de date, acest lucru nu este garantat).

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

    /**
     * Definește lista de ecrane permise (post_types)
     */
    private $_allowedScreens = array( 'SCREENS_TO_ALLOW_METABOX' );

    /**
     * Parametru GET pentru codul de eroare al cutiei de eroare
     */
    const GET_METABOX_ERROR_PARAM = 'meta-error';

    /**
     * Definește hook-urile pentru admin
     */
    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')); // NOTĂ: admin_notices nu poziționează acest lucru corect pe paginile de tip custom post type, nu am testat acest lucru pe POST sau PAGE dar nu văd aceasta ca pe o problemă
    }

    /**
     * Adaugă metabox-ul la tipurile de postări specificate
     */
    public function addMetabox() {
        foreach ( $this->_allowedScreens as $screen ) {
            add_meta_box(
                'PLUGIN_METABOX',
                __( 'TITLU', 'text_domain' ),
                array($this, 'metaBox'),
                $screen,
                'side',
                'high'
            );
        }
    }

    /**
     * Afișează conținutul metabox-ului
     * @param $post
     */
    public function metaBox($post) {
        // Adaugă un câmp nonce pentru a putea verifica mai târziu
        wp_nonce_field( 'metaboxnonce', 'metaboxnonce' );
        // Încarcă meta datele pentru acest metabox
        $someValue = get_post_meta( $post->ID, 'META_KEY_IDENTIFIER', true );
        ?>
        <p>
            <label for="some-value" style="width: 120px; display: inline-block;">
                <?php _e( 'Un câmp:', 'text_domain' ); ?>
            </label>
            &nbsp;
            <input type="text" id="some-value" name="some_value" value="<?php esc_attr_e( $someValue ); ?>" size="25" />
        </p>
    <?php
    }

    /**
     * Metodă de salvare pentru metabox
     * @param $post_id
     */
    public function saveMetabox($post_id) {
        global $wpdb;

        // Verifică dacă nonce-ul nostru este setat
        if ( ! isset( $_POST['metaboxnonce'] ) ) {
            return $post_id;
        }
        // Verifică dacă nonce-ul este valid
        if ( ! wp_verify_nonce( $_POST['metaboxnonce'], 'metaboxnonce' ) ) {
            return $post_id;
        }
        // Dacă acesta este un autosave, formularul nostru nu a fost trimis, așa că nu vrem să facem nimic
        if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
            return $post_id;
        }
        // Verifică permisiunile utilizatorului
        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;
            }
        }
        // Asigură-te că este setat
        if ( !isset( $_POST['some_value'] ) ) {
            return $post_id;
        }
        // Sanitizează input-ul utilizatorului
        $someValue = sanitize_text_field( $_POST['some_value'] );
        // Verifică să existe o valoare
        if (empty($someValue)) {
            // Adaugă codul nostru de eroare
            add_filter('redirect_post_location', function($loc) {
                return add_query_arg( self::GET_METABOX_ERROR_PARAM, 1, $loc );
            });
            return $post_id; // asigură-te că returnezi pentru a nu permite procesare suplimentară
        }
        // Actualizează câmpul meta în baza de date
        update_post_meta( $post_id, 'META_KEY_IDENTIFIER', $someValue );
    }

    /**
     * Notificări admin pentru metabox
     */
    public function adminNotices() {
        if (isset($_GET[self::GET_METABOX_ERROR_PARAM])) {
            $screen = get_current_screen();
            // Asigură-te că suntem în tipul de postare corect
            if (in_array($screen->post_type, $this->_allowedScreens)) {
                $errorCode = (int) $_GET[self::GET_METABOX_ERROR_PARAM];
                switch($errorCode) {
                    case 1:
                        $this->_showAdminNotice( __('A apărut o eroare', 'text_domain') );
                        break;
                    // Mai multe coduri de eroare pot fi adăugate aici pentru afișarea erorilor
                }
            }
        }
    }

    /**
     * Afișează notificarea admin pentru 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
    }

}
12 feb. 2015 17:11:54
Comentarii

Singura problemă pe care o am cu acest răspuns este că nu funcționează cu PHP 5.2. Nu spun că ar trebui să suportăm toți PHP 5.2, dar până când WordPress va avea PHP 5.2 ca cerință minimă, trebuie să-l suportăm dacă distribuim pluginul :(

Sudar Sudar
23 iun. 2015 06:47:20

Dacă elimini funcția anonimă și o faci o metodă publică, ar trebui să funcționeze bine. Înțeleg problema ta, dar personal nu voi dezvolta pentru o versiune EOL a PHP (http://php.net/eol.php) 5.2 EOL a fost pe 6 ianuarie 2011. WordPress ar trebui să depună mai mult efort pentru a nu suporta versiunile EOL, dar asta e altă poveste, la care se adaugă multe companii de hosting proaste care încă oferă versiuni EOL...

Jeremy Jeremy
23 iun. 2015 16:39:15