是否在保存自定义字段时添加验证和错误处理?

时间:2010-12-09 作者:MathSmath

我有一个函数,它在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\\u post操作,但我不知道如何处理错误。似乎没有错误对象传递到函数中,如果我创建自己的WP\\u error obj并返回它,那么无论何种机制在编辑后页面上抛出错误,都不会尊重它。

目前,我的自定义元框中有一条页面错误消息,但这并不理想——我宁愿有一个大的、红色的、顶部向上的错误,就像WP通常显示的那样。

有什么想法吗?

UPDATE:

根据@Denis的回答,我尝试了几种不同的方法。将错误存储为全局错误不起作用,因为Wordpress在save\\u post过程中执行重定向,这会在显示全局错误之前杀死全局错误。

我最终将它们存储在一个元字段中。问题是你需要清除它们,否则当你导航到另一个页面时,它们不会消失,所以我不得不在admin\\u页脚上添加另一个函数来清除错误。

我没想到对如此常见的事情(更新帖子)的错误处理会如此笨拙。我是否遗漏了一些明显的东西,或者这是最好的方法?

// 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\' );

7 个回复
最合适的回答,由SO网友:Denis de Bernardy 整理而成

将错误存储在类中或作为全局错误,可能存储在临时错误或元错误中,并在POST请求的管理通知中显示它们。WP没有任何flash消息处理程序。

SO网友:davidn

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

会话不是由wordpress启动的。所以你需要start a session 在插件中,函数。php甚至wp配置。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\' );

SO网友:Joshua Coady

基于pospi\'ssuggestion 使用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 在生成主页内容之前激发,通知不是其他post edit消息所在的位置,因此我必须使用此jQuery将其移动到那里:

jQuery(\'h2\').after(jQuery(\'#acme-plugin-message\'));
由于帖子ID是临时名称的一部分,因此除了多个用户同时编辑同一篇帖子外,这应该适用于大多数多用户环境。

SO网友:Lucas Bustamante

何时save_post 运行时,它已将帖子保存在数据库中

查看WordPress核心代码,更具体地说wp-includes/post.php\'supdate_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

SO网友:Horttcore

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

SO网友:jlub

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

SO网友:sanchothefat

我编写了一个插件,它为后期编辑屏幕添加了一个flash错误处理,并在填写必填字段之前阻止发布帖子:

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

它允许您强制设置任何post字段,但您也可以使用它提供的API,通过可自定义的错误消息和验证功能来设置任何所需的自定义字段。默认检查字段是否为空。

结束

相关推荐

Displaying oEmbed errors?

有时,通过oEmbed嵌入项目是不可能的,例如,当YouTube视频已禁用嵌入时。The oEmbed service will return a 401 Unauthorized, 并且不会转换代码。有没有办法通知用户这一点?当前的工作流是非直观的(至少对我来说),我更喜欢在WordPress页面上,或者更好的是,在编辑器中显示一条消息,说明对象无法嵌入。