问题描述

我有一个函数定义一个 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 辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:薇晓朵技术论坛。