問題描述

我有一個函式定義一個 post 型別的自定義欄位。說領域是”subhead” 。

儲存帖子後,我想對輸入進行一些驗證,並在必要時在後編輯螢幕上顯示錯誤訊息。就像是:

// Handle post updating
function wpse_update_post_custom_values($post_id, $post) {

    // Do some checking...
    if($_POST['subhead'] != 'value i expect') {

        // Add an error here
        $errors->add('oops', 'There was an error.');

    }

    return $errors;

} 
add_action('save_post','wpse_update_post_custom_values',1,2);

我試圖將它掛鉤到 save_post 操作,但我無法弄清楚如何處理錯誤。似乎沒有錯誤的物件傳遞到該函式,如果我建立我自己的 WP_Error 物件並返回它,它不被任何機制丟擲錯誤在後編輯頁面被尊重。

我目前在我的自定義元框中有一個 on-page 錯誤訊息,但這不太理想 – 我想要一個大的,紅色的,up-at-the-top 錯誤,如 WP 通常顯示。

有任何想法嗎?

更新:

基於 @Denis 的答案,我嘗試了幾件不同的事情。將錯誤作為全域性儲存不起作用,因為 WordPress 在 save_post 程式中執行重定向,這會在顯示之前殺死全域性。

我最終把它們儲存在一個元領域。這樣做的問題是,您需要清除它們,或者當您導航到另一個頁面時,它們不會消失,所以我不得不新增附加到 admin_footer 的另一個功能,只是清除錯誤。

我不會預料到這樣常見的錯誤處理 (更新帖子) 將是這個笨重的。我缺少一些明顯的東西,還是最好的方法?

// Handle post updating
function wpse_5102_update_post_custom_values($post_id, $post) {

    // To keep the errors in
    $errors = false;

    // Do some validation...
    if($_POST['subhead'] != 'value i expect') {

        // Add an error here
        $errors .= 'whoops...there was an error.';

    }

    update_option('my_admin_errors', $errors);

    return;

} 
add_action('save_post','wpse_5102_update_post_custom_values',1,2);


// Display any errors
function wpse_5102_admin_notice_handler() {

    $errors = get_option('my_admin_errors');

    if($errors) {

        echo '<div class="error"><p>' . $errors . '</p></div>';

    }   

}
add_action( 'admin_notices', 'wpse_5102_admin_notice_handler' );


// Clear any errors
function wpse_5102__clear_errors() {

    update_option('my_admin_errors', false);

}
add_action( 'admin_footer', 'wpse_5102_clear_errors' );

最佳解決方案

儲存您的課程中的錯誤或作為全域性的錯誤,可能是暫時的或後設資料,並在 POST 請求的管理通知中顯示。 WP 不具有任何 Flash 訊息處理程序。

次佳解決方案

我建議使用會話,因為這兩個使用者在同一時間編輯時不會產生奇怪的影響。所以這就是我所做的:

會話不是由 wordpress 開始的。所以你需要在你的外掛 start a session ,functions.php 甚至 wp-config.php:

if (!session_id())
  session_start();

儲存帖子時,會將錯誤和通知附加到會話中:

function my_save_post($post_id, $post) {
   if($something_went_wrong) {
     //Append error notice if something went wrong
     $_SESSION['my_admin_notices'] .= '<div class="error"><p>This or that went wrong</p></div>';
     return false; //might stop processing here
   }
   if($somthing_to_notice) {  //i.e. successful saving
     //Append notice if something went wrong
     $_SESSION['my_admin_notices'] .= '<div class="updated"><p>Post updated</p></div>';
   }

   return true;
} 
add_action('save_post','my_save_post');

列印通知和錯誤,然後清除會話中的訊息:

function my_admin_notices(){
  if(!empty($_SESSION['my_admin_notices'])) print  $_SESSION['my_admin_notices'];
  unset ($_SESSION['my_admin_notices']);
}
add_action( 'admin_notices', 'my_admin_notices' );

第三種解決方案

基於 pospisuggestion 使用 transients,我想出了以下幾點。唯一的問題是沒有鉤子將訊息放在 h2 下面的其他訊息去,所以我不得不做一個 jQuery 的駭客得到它在那裡。

首先,儲存 save_post(或類似) 處理程序的錯誤訊息。我給它一個短暫的 60 秒的生命週期,所以它只有足夠長的重定向發生。

if($has_error)
{
  set_transient( "acme_plugin_error_msg_$post_id", $error_msg, 60 );
}

然後,只需在下一頁載入並檢索該錯誤訊息即可。我也刪除它,所以它不會顯示兩次。

add_action('admin_notices', 'acme_plugin_show_messages');

function acme_plugin_show_messages()
{
  global $post;
  if ( false !== ( $msg = get_transient( "acme_plugin_error_msg_{$post->ID}" ) ) && $msg) {
    delete_transient( "acme_plugin_error_msg_{$post->ID}" );
    echo "<div id="acme-plugin-message" class="error below-h2"><p>$msg</p></div>";
  }
}

由於 admin_notices 在主頁內容生成之前觸發,所以通知不在其他帖子編輯訊息的位置,所以我不得不使用這個 jQuery 來移動它:

jQuery('h2').after(jQuery('#acme-plugin-message'));

由於帖子 ID 是臨時名稱的一部分,所以在大多數 multi-user 環境中都應該有效,除非多個使用者同時編輯同一個帖子。

參考文獻

注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。