Truyền các thông báo lỗi / cảnh báo từ một hộp meta đến


20

Tôi có một hộp meta đơn giản cập nhật các trường tùy chỉnh bài (sử dụng update_post_meta()).

Làm cách nào tôi có thể gửi thông báo lỗi hoặc cảnh báo đến trang tiếp theo sau khi người dùng xuất bản / cập nhật bài đăng và không điền vào một trong các trường của hộp meta (hoặc điền chúng với dữ liệu không hợp lệ)?

Câu trả lời:


9

Bạn có thể làm điều này bằng tay, nhưng WP thực sự thích nó cho các lỗi cài đặt:

  1. add_settings_error() để tạo thông điệp.
  2. Sau đó set_transient('settings_errors', get_settings_errors(), 30);
  3. settings_errors()trong admin_noticeshook để hiển thị (sẽ cần hook cho màn hình không cài đặt).

nó làm những gì tôi muốn, nhưng điều này sẽ không lấp đầy cơ sở dữ liệu với hàng tấn quá độ?
onetrickpony

@One Trick Pony trong quá trình bản địa tạm thời bị xóa rõ ràng (xem get_settings_errors()nguồn). Bạn có thể cần phải tự làm điều đó nếu điều chỉnh logic cho trang không cài đặt.
Rarst

2
Tuy nhiên, tôi không thích ý tưởng lưu trữ các thông báo lỗi tạm thời trong db. Tôi sẽ sử dụng ajax để cảnh báo người dùng về thay đổi đầu vào
onetrickpony

Với bộ nhớ đệm đối tượng, sự lộn xộn cơ sở dữ liệu sẽ không thành vấn đề.
lkraav

15

bạn có thể sử dụng admin_noticesmóc

đầu tiên xác định chức năng thông báo:

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

Hàm bạn lưu metabox dựa trên nếu cần thêm:

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

Cập nhật

Như tôi đã hứa ở đây là một ví dụ về cách tôi thêm một thông báo lỗi từ metabox của tôi

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

}

Bây giờ khi tìm mã này, tôi đã tìm thấy cách thực hiện cũ của mình bằng cách sử dụng post_updated_messagesbộ lọc hook theo cách tương tự vì vậy tôi cũng sẽ thêm nó vào:

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

không thực sự hoạt động vì sau khi bạn lưu bài đăng, bạn sẽ được chuyển hướng để hành động đó không bao giờ chạy ...
onetrickpony

1
Chuyển hướng ở đâu? Và đoạn mã trên là tôi sử dụng để tôi biết nó hoạt động.
Bai Internet

chức năng lưu metabox của bạn được nối vào save_post?
onetrickpony

1
cảm ơn, nhưng điều này thực hiện tương tự như Rarst đã chỉ ra: thông báo lỗi được lưu trong db, sau đó lấy ra và xóa trên trang tiếp theo.
onetrickpony

1
-1 để sử dụng DB. Bạn không thể đảm bảo người dùng chính xác sẽ thấy lỗi. Ngoài ra, không có giá trị chi phí không cần thiết. Đối với việc không có cách cắt rõ ràng để xử lý lỗi metabox, đây là một cách làm việc tốt nhưng vẫn không hiệu quả. Tôi đã thêm một ví dụ về cách tôi làm điều này trong một câu trả lời mới để giúp đỡ người khác.
Jeremy

11

Câu trả lời này [ gương ] từ Otto trong WP Tavern, thực sự giải quyết vấn đề nhất thời bằng cách làm những gì chính WordPress làm để khắc phục vấn đề chuyển hướng. Hoàn toàn làm việc cho tôi.

Vấn đề là sự tạm thời ở đó cho tất cả mọi người. Nếu bạn có nhiều người dùng làm cùng một lúc, thông báo lỗi có thể đến nhầm người. Đó là một điều kiện chủng tộc.

WordPress thực sự làm điều này bằng cách chuyển một tham số tin nhắn trong URL. Số tin nhắn cho biết tin nhắn nào sẽ hiển thị.

Bạn có thể làm tương tự bằng cách nối redirect_post_locationbộ lọc và sau đó sử dụng add_query_argđể thêm tham số của riêng bạn vào yêu cầu. Thích như vậy:

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

Điều này thêm my_message=123vào truy vấn. Sau đó, sau khi chuyển hướng, bạn có thể phát hiện cài đặt my_message trong $_GETvà hiển thị thông báo phù hợp.


3

Tôi biết câu hỏi này đã cũ nhưng tôi tìm thấy câu trả lời ở đây để không giải quyết vấn đề.

Mở rộng câu trả lời từ Ana Ban, sử dụng phương pháp của Otto , tôi thấy đây là phương pháp tốt nhất để xử lý lỗi. Điều này không yêu cầu lưu trữ các lỗi trong db.

Tôi đã bao gồm một phiên bản rút gọn của một đối tượng Metabox mà tôi sử dụng. Điều này cho phép tôi dễ dàng thêm các thông báo lỗi mới và đảm bảo người dùng chính xác nhìn thấy thông báo lỗi (sử dụng db, đây không phải là bảo đảm).

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

}

Vấn đề duy nhất tôi có với câu trả lời này là nó không hoạt động với PHP 5.2. Tôi không nói rằng tất cả chúng ta nên hỗ trợ HPP 5.2, nhưng cho đến khi WordPress có PHP 5.2 là yêu cầu tối thiểu, chúng tôi cần hỗ trợ nó nếu chúng tôi đang phân phối plugin :(
Sudar

1
Nếu bạn loại bỏ hàm ẩn danh và biến nó thành một phương thức công khai, nó sẽ hoạt động tốt. Tôi hiểu vấn đề của bạn nhưng cá nhân tôi sẽ không phát triển phiên bản EOL của PHP ( php.net/eol.php ) 5.2 EOL là ngày 6 tháng 1 năm 2011. WordPress nên nỗ lực nhiều hơn để không hỗ trợ các phiên bản EOL nhưng đó là một câu chuyện khác cộng với nhiều công ty lưu trữ tồi vẫn cung cấp các phiên bản EOL ...
Jeremy
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.