我有一个在帖子类型上定义自定义字段的函数。假设该字段为“副标题”。像这样的东西:

// 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 obj并返回它,则无论哪种机制都不会在后期编辑页面上吐出错误。

目前,我的自定义meta框内有一个页面错误消息,但这并不理想-我宁愿有一个大的,红色的,最顶部的错误,如WP通常显示。
有什么想法吗?

更新:将错误存储为全局变量是行不通的,因为Wordpress在save_post过程中进行了重定向,这会在显示全局变量之前将其杀死。

我最终将它们存储在meta字段中。问题是您需要清除它们,否则当您导航到另一个页面时它们不会消失,因此我不得不在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' );


评论

好问题。我认为,如果在通知处理程序函数末尾清除错误,就可以摆脱admin_footer挂钩。简化了一些事情。

您如何处理重新填充表单字段(可能包含无效数据)的问题?

我有一个基本问题。这是什么Wordpress php文件?

@Karen这将在自定义插件文件或您的functions.php中。

我可能会遗漏一些明显的东西,但是运行update_option('my_admin_errors',false)会更有效些吗?在wpse_5102_admin_notice_handler()末尾的if语句之后吗?

#1 楼

将错误存储在您的类中或全局变量中,可能在瞬态或元数据中存储,并在POST请求的管理员通知中显示它们。 WP没有任何Flash消息处理程序。

评论


感谢您指出我的方向!我最终使用meta来存储错误,因为尝试将其作为全局属性或属性时遇到了问题。我现在正在更新我的答案,以解释我的工作方式...请让我知道这是否是您建议的那种方式,或者是否有更好的方法让我无法理解。

–MathSmath
2010-12-10在0:15

是的,是的。不过,也许您会再三考虑将其存储在会话变量中。这是为了使多个作者可以同时编辑帖子。 :-)另外,我相信不可能在选项中存储false。而是存储一个空字符串。

–丹尼斯·伯纳迪(Denis de Bernardy)
2010-12-10 9:35

#2 楼

我建议使用会话,因为当两个用户同时进行编辑时,这不会产生奇怪的效果。因此,这就是我的工作:

会话不是由wordpress启动的。因此,您需要在插件,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' );


评论


修复会话版本:第一次使用会话变量时不要使用。= only =如果打开调试,则可以检查原因...

–user18140
2012年7月13日在13:12

我也一直在这样做,但是如果您向如此广泛的受众发布插件,人们最终会讨厌您。 Wordpress不会实例化会话,因为它被设计为无状态的并且不需要它们,并且一些奇怪的服务器设置会破坏它。使用过渡API-codex.wordpress.org/Transients_API代替会话,您将保持兼容性。只是认为值得在此标记出不这样做的原因。

–pospi
2012年9月12日在1:37



@pospi似乎与最初使用get_option和update_option函数有类似的问题。因此,我猜解决方案是将当前用户的ID附加到密钥上?

–万亿
13-10-24在16:55

是的,完全可以!只要您添加一些东西来唯一标识用户,就可以避免登录用户之间的消息混淆(:

–pospi
13年10月28日在0:23

#3 楼

基于pospi的使用瞬态的建议,我提出了以下建议。唯一的问题是,没有钩子可以将消息放置在其他消息所在的h2下方,因此我不得不做一个jQuery hack才能将其保存到那里。 (或类似)处理程序。我为它提供了60秒的短生命周期,因此它足够长,可以进行重定向。

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


然后,仅在下一次检索该错误消息页面加载并显示它。我也将其删除,这样它就不会显示两次。 ,因此我不得不使用此jQuery将其移至该位置:

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


由于帖子ID是临时名称的一部分,因此它在大多数多用户环境中均应适用除非多个用户同时编辑同一个帖子。

评论


您能否详细说明“由于帖子ID是临时名称的一部分”?我使用这种技术创建了一个处理错误消息的类,但是我需要我的构造函数传递一个user_ID。散列密钥时,瞬态API是否使用user_id? (我问,因为法典似乎没有提到这一点)

–万亿
13-10-24在17:37

否,但是您可以手动添加它。在我上面发布的代码中,瞬变的名称为acme_plugin_error_msg_POSTID。您可以像acme_plugin_error_msg_POSTID_USERID这样添加用户ID。

–约书亚·科迪(Joshua Coady)
15年1月30日在4:34

#4 楼

save_post运行时,它已经将帖子保存在数据库中。
查看WordPress核心代码,更具体地说,在wp-includes/post.phpupdate_post()函数中,没有内置的方法可以在保存请求之前拦截请求。数据库。
但是,我们可以钩住pre_post_update并使用header()get_post_edit_link()来防止帖子被保存。
<?php

/**
*   Performs validation before saving/inserting custom post type
*/
function custom_post_site_save($post_id, $post_data) {
    // If this is just a revision, don't do anything.
    if (wp_is_post_revision($post_id))
        return;

    if ($post_data['post_type'] == 'my_custom_post_type') {
        // Deny post titles with less than 5 characters
        if (strlen($post_data['post_title'] < 5)) {
            header('Location: '.get_edit_post_link($post_id, 'redirect'));
            exit;
        }
    }
}
add_action( 'pre_post_update', 'custom_post_site_save', 10, 2);

如果要通知用户出了什么问题,请检查以下要点:https ://gist.github.com/Luc45/09f2f9d0c0e574c0285051b288a0f935

评论


谢谢您,无论是首次发布还是更新帖子,都可以完美地处理验证。您节省了我很多时间和精力。

–扎德
18/12/15在8:31

#5 楼

为什么不借助一些Javascript来验证您的字段?
我认为这将是最好的方法。

评论


谢谢你的建议!为了简单起见,我没有考虑这个问题,因为我正在尝试处理文件上传错误,因此它需要在服务器端进行。还是)感谢你的建议!

–MathSmath
2010-12-10 16:33

javascript验证不能阻止某些攻击,服务器端验证是唯一安全的方法。此外,wordpress提供了一些很好的工具来验证用户数据。但是,如果它只是在将数据发送到服务器之前检查一些值,那么您是对的,您可以在低服务器中节省一些时间^^

–磨牙
2011年3月14日23:50

#6 楼

尝试使用上面的脚本时,我遇到了一个奇怪的问题。帖子更新后,编辑屏幕上会显示两条消息。一种显示来自先前保存的内容状态,另一种显示当前内容的状态。例如,如果我正确保存帖子,然后出错,则第一个是“ error”,第二个是“ ok”-尽管它们是同时生成的。如果我更改脚本并仅添加一条消息(例如“错误”),请使用“错误”启动一个更新,然后使用“确定”进行另一次更新,“错误”消息将保留(第二次显示)。我必须再次保存“确定”才能摆脱它。我真的不知道出什么问题了,我已经在三台不同的本地服务器上对其进行了测试,并且每台服务器上都存在相同的问题。如果有人有任何想法或建议,请帮忙!

评论


我对上面提到的脚本的第二个版本进行了更多测试,并且看来,如果“错误”消息确实附加在会话数组上,则会显示在编辑屏幕上。如果没有消息(一切正常),并且上一条消息是错误的,它将显示在屏幕上。奇怪的是,它是在保存时生成的(未缓存)-我已经在错误消息正文中使用date()对其进行了检查。我现在很困惑。

– jlub
2011年9月8日在17:55

好的,以防万一其他人将头发拔掉了-事实证明,WordPress修订系统是问题所在(可能是某种错误?)。我已禁用它,现在一切都很好。

–user8594
2011-09-12 9:41

#7 楼

我编写了一个插件,该插件添加了用于帖子编辑屏幕的Flash错误处理功能,并可以防止在发布必填字段之前发布帖子:

https://github.com/interconnectit/required-fields

它允许您将任何帖子字段都设为必填项,但是您可以使用它提供的API,通过可自定义的错误消息和验证功能来使所有必填字段都必需。默认情况下检查该字段是否为空。

评论


如果遇到它们,请不要在github上添加任何问题。我还需要更好地记录API,因为您可以使用一些辅助过滤器。

– sanchothefat
2012年12月7日下午14:13