在WordPress中显示save_post挂钩中的错误

Despite the existence of WP_Error and all the pieces required, there is no single “WordPress Way” to handle and display errors. You can indicate an error occurred in a function or method by returning the WP_Error object (and that’s been my usual MO in my work), but once we do, how do we handle these error objects?

尽管存在WP_Error和所需的所有组件,但没有单一的“ WordPress方式”可以处理和显示错误。 您可以通过返回WP_Error对象(这是我工作中通常的MO)来指示函数或方法中发生了错误,但是一旦完成,我们如何处理这些错误对象?

WordPress Errors

It’s easy on the AJAX side of things: Use wp_send_json_{error/success} and handle the response accordingly. However, a common area where generated errors need to be displayed to the user is on the save_post hook, which is actually slightly more complicated than it looks.

在AJAX方面很容易:使用wp_send_json_{error/success}并相应地处理响应。 但是,需要向用户显示所生成的错误的常见区域位于save_post挂钩上,该区域实际上比看起来要复杂一些。

The reason for this is due to the way WordPress handles saves. If you’re on a page like post.php?post=1234 and you make your edits and hit save, WordPress POST’s the information to post.php. After the save_post hook fires, everything that’s done is done, it then redirects back to the post.php?post=1234 editor page.

这样做的原因是由于WordPress处理保存的方式。 如果您位于诸如post.php?post=1234类的页面上,然后进行编辑并单击“ 保存” ,则WordPress POST就是post.php的信息。 在save_post钩子触发之后,完成的所有操作都将完成,然后重定向回到post.php?post=1234编辑器页面。

This makes things difficult because the redirect means the execution thread for loading the editor page isn’t the same as the thread for saving the post, and we no longer have access to the same global variables we did when we were saving. Because of this, we need a way to pass that information from the action to the page we’re being redirected to.

这使事情变得困难,因为重定向意味着用于加载编辑器页面的执行线程与用于保存帖子的线程不同,并且我们不再有权访问与保存时相同的全局变量。 因此,我们需要一种方法来将该信息从操作传递到要重定向到的页面。

Let’s walk through 3 potential methods of solving this problem. I’ll explain how to implement each one, point out some of their pros and cons, and explain to which contexts they’re best suited.

让我们逐步介绍解决此问题的3种潜在方法。 我将说明如何实现每个方案,指出它们的一些优点和缺点,并说明它们最适合的上下文。

参考样板 (Reference Boilerplate)

Before we get started, I’m going to be using the admin_notices hook for error displaying, which looks like this:

在开始之前,我将使用admin_notices钩子来显示错误,如下所示:

add_action( 'admin_notices', 'my_error_message' );

This hook gives us a place to display messages above the page title. I’ll detail the my_error_message function for each method as we go. I’m also going to ignore whatever you decide to do in the save_post hook and just assume you end up at the end of the hook with an $error, which is either false if there were no errors or a WP_Error object if there was. The execution flow would look something like this:

该挂钩为我们提供了一个在页面标题上方显示消息的地方。 我们将详细介绍每种方法的my_error_message函数。 我还将忽略您决定在save_post挂钩中执行的任何操作,而只是假设您最终在挂钩末尾遇到$error ,如果没有错误,则为false如果存在, WP_Error对象。 执行流程如下所示:

add_action( 'save_post', 'my_save_post_function' );
function my_save_function( $post_id ) {
    $error = false;

    // Do stuff.

    if ($something_went_wrong) {
        $error = new WP_Error($code, $msg);
    }

    if ($error) {
        // Handle error.
    }

    return true;
}

Something happens with the $post_id (not pictured), and if something goes wrong, we’ll create a WP_Error object which we’ll handle.

$post_id会发生某些情况(未显示),如果出现问题,我们将创建一个WP_Error对象,该对象将处理。

将其保存在$_SESSION (Save It in the $_SESSION)

PHP (and WordPress, actually) is (in)famous for its globals. Similar to how the $_GET and $_POST variables hold the data for those HTTP verbs, the $_SESSION global holds the data for the current session. The $_SESSION data is persisted in the configured session storage (e.g. memcache, Redis, filesystem) and tied to the user’s session through a cookie. We can use that to save and retrieve our error message.

PHP(实际上是WordPress)以其全局性而闻名。 类似于$_GET$_POST变量如何保存这些HTTP动词的数据, $_SESSION全局变量可以保存当前会话的数据。 $_SESSION数据将保留在配置的会话存储中(例如,内存缓存,Redis,文件系统),并通过cookie绑定到用户的会话。 我们可以使用它来保存和检索错误消息。

这个怎么运作 (How It Works)

First, you’ll have to initiate the session, as WordPress doesn’t use sessions on its own:

首先,您必须启动会话,因为WordPress本身并不使用会话:

if ( !session_id() ) {
    session_start();
}

This should be hooked early in the WordPress lifecycle, although I think you could start the session in the save_post hook itself if you’d like. Then, we save the error to the session:

这应该在WordPress生命周期的早期就被钩住了,尽管我认为您可以根据需要在save_post钩子本身中启动会话。 然后,我们将错误保存到会话中:

if ($error) {
    $_SESSION['my_plugin_errors'] = $error->get_error_message();
}

Finally, in the admin_notices hook:

最后,在admin_notices钩子中:

if ( array_key_exists( 'my_plugin_errors', $_SESSION ) ) {?>
    <div class="error">
        <p><?php echo $_SESSION['my_plugin_errors']; ?></p>
    </div><?php

    unset( $_SESSION['my_plugin_errors'] );
}

we pull the error message from the session and output it above the page title.

我们从会话中提取错误消息,并将其输出到页面标题上方。

利弊 (Pros and Cons)

On the plus side, this solution is fairly easy to implement and doesn’t require you to hit the database, which the other two solutions do. The major problem with it is: WordPress doesn’t use sessions. It’s designed to be “stateless,” so it’s not designed to maintain information as it proceeds through its operations, which will cause problems for some users if they don’t have a session store. Fundamentally, it’s not “The WordPress Way” and runs counter to the philosophy of the project, but it is an easy and lightweight solution to the problem if you’re building a tool for yourself or a client, where you have full control over the environment.

从正面来看,该解决方案非常易于实现,不需要您访问数据库,而其他两种解决方案都可以。 它的主要问题是: WordPress不使用session 。 它被设计为“无状态”,因此它并非旨在在信息进行操作时维护信息,如果某些用户没有会话存储,这将给他们带来麻烦。 从根本上讲,这不是“ WordPress方式”,并且与项目理念背道而驰,但是,如果您要为自己或客户构建工具,而您可以完全控制该工具,则它是解决该问题的简便轻便的解决方案。环境。

暂时保存 (Saving It in a Transient)

Transients are a WordPress caching API. It allows you to save any kind of information with an expiration date, like you would in any other cache. Under the hood, the Transient API will attempt to save your data to the object cache, if you have a persistent cache enabled. If you don’t, it will save your data to the wp_options table. This way, no matter how the site’s back-end is configured there’s a (somewhat) reliable API for persisting short-term data. It abstracts a lot of hard work for you.

瞬态是WordPress缓存API。 它允许您使用到期日期保存任何类型的信息,就像在其他任何缓存中一样。 如果启用了持久性缓存 ,则Transient API会尝试将您的数据保存到对象缓存中。 如果您不这样做,它将把您的数据保存到wp_options表中。 这样,无论网站的后端如何配置,都有一个(某种)可靠的API可以保存短期数据。 它为您提取了很多艰苦的工作。

One word of caution: While the data should be there (and for the short period of time we’re saving it for, it almost always will be) when we get it, there are reasons it could get lost, especially of it’s being saved to the object cache. You can’t assume the data will always be there. If you absolutely need the information to persist, you should save it to the database directly.

一个警告:当我们得到数据时,虽然数据应该在那里(并且在很短的时间内保存,几乎总是会保存),但是有一些原因可能会丢失,尤其是正在保存到对象缓存。 您不能假设数据将一直存在。 如果绝对需要保留信息,则应将其直接保存到数据库中。

这个怎么运作 (How It Works)

We don’t need to initiate anything to get started with transients. When you get an error, just set a transient with the information (you’ll need to fetch the $user_id in advance):

我们不需要启动任何东西就可以开始瞬态。 当您收到错误消息时,只需设置一个瞬态信息即可(您需要预先获取$user_id ):

if ($error) {
    set_transient("my_save_post_errors_{$post_id}_{$user_id}", $error, 45);
}

Here’s the reference for that function. Just note that the last param is the number of seconds that the transient will last for. 45 seconds should be enough time to save and get the data, and if it isn’t, something has gone horribly wrong.

这是该功能的参考 。 请注意,最后一个参数是瞬态持续的秒数。 45秒应该足以保存和获取数据,如果不是,则说明出现了严重错误。

Then, in the admin_notices hook:

然后,在admin_notices钩子中:

if ( $error = get_transient( "my_save_post_errors_{$post_id}_{$user_id}" ) ) { ?>
    <div class="error">
        <p><?php echo $error->get_error_message(); ?></p>
    </div><?php

    delete_transient("my_save_post_errors_{$post_id}_{$user_id}");
}

we grab the WP_Error from the cache and display its message. Don’t forget to clean up after yourself!

我们从缓存中获取WP_Error并显示其消息。 不要忘了自己清理!

利弊 (Pros and Cons)

On the plus side, this is a WordPress-friendly way of managing these errors, designed for caching stuff like this. The data will be cleared out on its own, even if you forget to clear it yourself, so it provides a kind of sanity check for you, wiping or ignoring stale error messages. The primary problem with this solution is it has to hit the database if you don’t have an object cache installed, so if you’re doing a lot of work in the save_post hook and don’t want to add another query, this may not be the ideal solution.

从好的方面来说,这是管理这些错误的WordPress友好方法,旨在缓存此类内容。 即使您忘记自己清除数据,数据也会自行清除,因此它为您提供了一种完整性检查,可以擦除或忽略陈旧的错误消息。 此解决方案的主要问题是,如果您没有安装对象缓存,则必须访问数据库,因此,如果您在save_post挂钩中做了很多工作并且不想添加其他查询,则可能并不是理想的解决方案。

I’ll also mention you can use this same idea with post_meta. If I recall correctly, this may not add an extra query, as it just adds a statement to the query for the post, but I’m not sure. Using post_meta for temporary data isn’t really it’s ideal purpose, but if it gives you a performance boost, it may be worth it. Definitely make sure to clean up after yourself then, since that won’t be done for you with post_meta the way transients do.

我还要提到您可以在post_meta使用相同的想法。 如果我没记错的话,这可能不会添加额外的查询,因为它只是为该帖子的查询添加了一条语句,但我不确定。 将post_meta用于临时数据并不是真正的理想目的,但是如果可以提高性能,那也许是值得的。 一定要确保自己之后进行清理,因为post_metatransients那样为您完成post_meta

向重定向添加GET参数 (Adding a GET Param to the Redirect)

This third method is actually the way WordPress shows its “Post Updated” message: with a $_GET param. In WordPress’s instance, it sets the message value to a number, and uses that number to display a particular message. You can do something similar, adding the WP_Error’s code, instead of its full message, to the URL as a query variable.

第三种方法实际上是WordPress显示其“更新后”消息的方式:使用$_GET参数。 在WordPress的实例中,它将message值设置为一个数字,并使用该数字显示特定的消息。 您可以执行类似的操作,将WP_Error的代码而不是其完整消息添加到URL作为查询变量。

At the end of our save_post hook, we add the error code to the URL parameter:

save_post挂钩的末尾,我们将错误代码添加到URL参数中:

if ($error) {
    add_filter('redirect_post_location', function( $location ) use ( $error ) {
        return add_query_arg( 'my-plugin-error', $error->get_error_code(), $location );
    });
}

Anonymous functions weren’t ADDED until PHP 5.3, and WordPress supports 5.2+, so their use here may disqualify you from this method, but this is a pretty ideal use case for them, pulling in a variable from its context and using it in the filter.

直到PHP 5.3才添加匿名函数,而WordPress支持5.2+,因此在此使用它们可能使您无法使用此方法,但这对他们来说是一个非常理想的用例,它从上下文中提取变量并将其用于过滤。

Then, we display the error message, based on its code, in the admin_notices hook:

然后,我们根据错误代码在admin_notices挂钩中显示错误消息:

if ( array_key_exists( 'my-plugin-error', $_GET) ) { ?>
    <div class="error">
        <p>
            <?php
                switch($_GET['my-plugin-error']) {
                    case 'an_error_code':
                        echo 'The post failed to save because problems.';
                        break;
                    case 'another_error_code':
                        echo 'The post failed to save because reasons.';
                        break;
                    default:
                        echo 'An error ocurred when saving the post.';
                        break;
                }
            ?>
        </p>
    </div><?php
}

利弊 (Pros and Cons)

The big plus on this is you never have to hit the database. All of the error codes are stored and retrieved in memory, which makes it much more performant than the others. The negative side is you have to duplicate the messages in both the instantiation of the WP_Error object and the switch statement. You can’t use a constant or a set of variables or anything like that because then the strings can’t be translated. If you have a limited number of error codes, this shouldn’t be an issue, but if your application gets large, it could be more difficult to maintain long-term.

最大的好处是您不必打数据库。 所有错误代码都存储在内存中并在其中检索,这使其比其他错误代码具有更高的性能。 不利的一面是您必须在WP_Error对象的实例化和switch语句中都复制消息。 您不能使用常量或变量集或类似的东西,因为这样字符串就不能被翻译。 如果错误代码的数量有限,那么这不成问题,但是如果您的应用程序变大,则长期维护可能会更加困难。

结论 (Conclusion)

Each of these three methods are better or easier to implement in various situations. I like to use transients to pass data around across page loads, especially when displaying error messages the user needs to see and possibly react to. The query variable has the lowest overhead of all three, and works great when your application only generates a small number of errors. And while the session isn’t really supported by WordPress, it is a common method for flashing messages to the user in other applications.

这三种方法中的每一种在各种情况下都更好或更容易实现。 我喜欢使用瞬态来跨页面加载传递数据,尤其是在显示用户需要查看并可能做出响应的错误消息时。 查询变量在这三个变量中的开销最低,并且在您的应用程序仅生成少量错误时效果很好。 尽管WordPress并不真正支持该会话,但它是在其他应用程序中向用户刷新消息的常用方法。

I hope that these potential approaches to displaying errors have been useful to you. Leave me a comment if you have any questions.

我希望这些显示错误的潜在方法对您有所帮助。 如有任何疑问,请给我留言。

翻译自: https://www.sitepoint.com/displaying-errors-from-the-save_post-hook-in-wordpress/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值