处理POST请求以WordPress方式

Get the Right File Permissions in Your WordPress Site with our tutorial.

通过我们的教程在WordPress网站中获取正确的文件权限

An interactive website needs to be able to interact with user input, which is commonly in the form of form submissions. A WordPress site is no exception to this rule. There are various interactions happening on a website on a daily basis. For example, subscribing to a newsletter, sending a message to the site owner and filling in an order form. All of these usually happen from POST requests during a form submission.

交互式网站需要能够与用户输入进行交互,而用户输入通常采用表单提交的形式。 WordPress网站也不例外。 每天在网站上发生各种交互。 例如,订阅时事通讯,向站点所有者发送消息并填写订单。 所有这些通常是在表单提交期间通过POST请求发生的。

WordPress Transients API

In this article, we’re going to take a simple example of handling a POST request from a user, which is submitted via a contact form. We are going to use an internal WordPress hook to properly get the data, process it accordingly and redirect the user back to a specific page.

在本文中,我们将以一个简单的示例来处理来自用户的POST请求,该请求是通过联系表单提交的。 我们将使用内部WordPress挂钩正确获取数据,进行相应处理,然后将用户重定向回特定页面。

This article assumes you have a basic knowledge of the WordPress Plugin API. If you’re not familiar, it’s highly recommended to review the Codex page first.

本文假定您具有WordPress插件API的基本知识。 如果您不熟悉,强烈建议您先阅读Codex页面。

背景 (The Background)

WordPress is based on an event driven architecture. This means internally, WordPress core is filled up with various actions and filters to modify the program execution or to alter the content during runtime. Examples of actions that are running during program execution are init, wp, template_redirect and wp_head. Many plugins utilise these actions and filters to modify how WordPress works.

WordPress基于事件驱动的体系结构 。 这意味着在内部,WordPress核心充满了各种操作和过滤器,以修改程序执行或在运行时更改内容。 initwptemplate_redirectwp_head是在程序执行期间运行的操作的示例。 许多插件利用这些动作和过滤器来修改WordPress的工作方式。

It is no different with what we are going to achieve. All we need to know is the proper hooks needed for the POST request and to modify our code accordingly. This is possible by pointing all our form submissions to a specific file in the wp-admin directory called admin-post.php. If you have experienced integrating your application with WordPress internal AJAX API, then you will notice that the basic structure of admin-post.php is not much different to the admin-ajax.php counterpart.

我们要实现的目标没有什么不同。 我们需要知道的是POST请求所需的正确钩子,并相应地修改我们的代码。 通过将我们所有的表单提交指向wp-admin目录中名为admin-post.php的特定文件,这是可能的。 如果你经历了整合与您的应用程序WordPress的内部AJAX API ,那么你会发现,基本结构admin-post.php是不是备受不同的admin-ajax.php对应。

admin-post.php的剖析 (Anatomy of admin-post.php)

At the very basic level, admin-post.php only contains 71 lines of code. It starts by defining WP_ADMIN constant and then loading WordPress by requiring wp-load.php. After that it sends an appropriate header and triggers the admin_init action.

在最基本的级别上, admin-post.php仅包含71行代码 。 首先定义WP_ADMIN常量,然后通过要求wp-load.php加载WordPress。 之后,它将发送适当的标头并触发admin_init操作。

The current action is determined by this line of code:

当前操作由以下代码行确定:

$action = empty( $_REQUEST['action'] ) ? '' : $_REQUEST['action'];

Despite the name, admin-post.php can actually handle both of POST and GET requests. However, what we’re interested to go through in the context of this article will be only related to POST request. Next,

尽管名称, admin-post.php实际上可以处理POSTGET请求。 但是,我们在本文中感兴趣的内容仅与POST请求有关。 下一个,

if ( ! wp_validate_auth_cookie() ) {
    if ( empty( $action ) ) {
        /**
         * Fires on a non-authenticated admin post request where no action was supplied.
         *
         * @since 2.6.0
         */
        do_action( 'admin_post_nopriv' );
    } else {
        /**
         * Fires on a non-authenticated admin post request for the given action.
         *
         * The dynamic portion of the hook name, `$action`, refers to the given
         * request action.
         *
         * @since 2.6.0
         */
        do_action( "admin_post_nopriv_{$action}" );
    }
} else {
    if ( empty( $action ) ) {
        /**
         * Fires on an authenticated admin post request where no action was supplied.
         *
         * @since 2.6.0
         */
        do_action( 'admin_post' );
    } else {
        /**
         * Fires on an authenticated admin post request for the given action.
         *
         * The dynamic portion of the hook name, `$action`, refers to the given
         * request action.
         *
         * @since 2.6.0
         */
        do_action( "admin_post_{$action}" );
    }
}

We can see that two different action hooks will be triggered based on the user logged in status which is admin_post for logged in user and admin_post_nopriv for the non logged in user. If you need a more refined control to only processing the data related to your request, a more specific action will also be triggered, namely admin_post_nopriv_{$action} and admin_post_{$action}, again based on the logged in state of the user.

我们可以看到两个不同的动作钩子将根据用户的登录状态,它会被触发admin_post在用户登录和admin_post_nopriv对于非登录用户。 如果您需要一个更精细的控件来仅处理与您的请求相关的数据,则还将基于用户的登录状态触发更具体的操作,即admin_post_nopriv_{$action}admin_post_{$action}

Let’s say our POST request has an action with a value of foobar. These two actions will be triggered if the current user is not logged in:

比方说,我们的POST请求有一个action ,值为foobar 。 如果当前用户未登录,将触发以下两个操作:

  • admin_post_nopriv

    admin_post_nopriv

  • admin_post_nopriv_foobar

    admin_post_nopriv_foobar

If you are currently logged in, two different actions will be triggered:

如果您当前登录,将触发两个不同的操作:

  • admin_post

    admin_post

  • admin_post_foobar

    admin_post_foobar

For GET request, when you are accessing the URL like this:

对于GET请求,当您像这样访问URL时:

http://www.example.com/wp-admin/admin-post.php?action=foobar&data=test

All the above four hooks are still available to you to use.

以上所有四个挂钩仍可供您使用。

With this knowledge, we can easily hook into the appropriate actions to handle the contact form submission without actually messing with our theme template.

有了这些知识,我们可以轻松地采取适当的措施来处理联系表单提交,而无需实际弄乱我们的主题模板。

概念证明 (Proof of Concept)

Let’s take a contact form as an example. The simplest way to do this (not recommended) is perhaps to create a custom page template based on the basic page.php, hardcode a form and do the processing in that file itself. This is roughly how it looks:

让我们以联系表​​为例。 最简单的方法(不建议这样做)可能是基于page.php创建自定义页面模板,对表单进行硬编码并在该文件本身中进行处理。 大致如下所示:

<?php
/*
 * Template Name: Contact Page
 */

get_header();

if ( ! empty( $_POST ) ) {
    // Sanitize the POST field
    // Generate email content
    // Send to appropriate email
}

?>

<div id="content">
    <form action="" method="post">
        <label for="fullname">Full Name</label>
        <input type="text" name="fullname" id="fullname" required>
        <label for="email">Email Address</label>
        <input type="email" name="email" id="email" required>
        <label for="message">Your Message</label>
        <textarea name="message" id="message"></textarea>
        <input type="submit" value="Send My Message">
    </form>
</div>

<?php
get_footer();

While this implementation will work, there is no separation or concern whatsoever which will lead to trouble in the long run. Maintaining the form is a nightmare as the processing is only happening in one place, and if we are to duplicate the form somewhere else, we need to redo the processing again.

尽管此实现将起作用,但没有任何隔离或担忧,从长远来看,这将导致麻烦。 维护表单是一场噩梦,因为处理仅在一个地方进行,如果要在其他地方复制该表单,则需要再次重做该处理。

To fully utilize the event driven nature of WordPress, and also to provide a separation of concern, we can make use of the admin-post.php provided. Converting the existing form to make it compatible with admin-post.php is fairly straightforward too.

为了充分利用WordPress的事件驱动性质,并提供关注点分离,我们可以使用提供的admin-post.php 。 转换现有形式使其与admin-post.php兼容也非常简单。

We first change this line from:

我们首先将这一行更改为:

<form action="" method="post">

to:

至:

<form action="<?php echo esc_url( admin_url('admin-post.php') ); ?>" method="post">

To generate a proper URL pointing to the admin-post.php, we use the built-in function admin_url. This will make sure that our URL is always correct in reference to the current site that is running.

为了生成指向admin-post.php的正确URL,我们使用内置函数admin_url 。 这将确保我们的URL相对于正在运行的当前站点始终是正确的。

We also need to add the action hidden input so that we can trigger the more specific hook related to our contact form submission. Let’s use an example of contact_form for the action value.

我们还需要添加action隐藏输入,以便我们可以触发与联系表单提交相关的更具体的挂钩。 让我们使用一个contact_form示例作为action值。

We add this line somewhere in between the <form> tag.

我们将此行添加在<form>标记之间的某处。

<input type="hidden" name="action" value="contact_form">

This is how the page template looks like after the modification:

修改后的页面模板如下所示:

<?php
/*
 * Template Name: Contact Page
 */

get_header();
?>

<div id="content">
    <form action="<?php echo esc_url( admin_url('admin-post.php') ); ?>" method="post">
        <label for="fullname">Full Name</label>
        <input type="text" name="fullname" id="fullname" required>
        <label for="email">Email Address</label>
        <input type="email" name="email" id="email" required>
        <label for="message">Your Message</label>
        <textarea name="message" id="message"></textarea>
        <input type="hidden" name="action" value="contact_form">
        <input type="submit" value="Send My Message">
    </form>
</div>

<?php
get_footer();

Notice that we are removing the POST processing function on top of the template since we are going to hook into the action later on.

注意,由于稍后我们将挂接到动作中,因此我们将删除模板顶部的POST处理功能。

POST请求的实际处理 (Actual Handling of the POST Request)

For this part, we have two options, and going with either one is fine. We can either hook into the admin_post_* action via the functions.php of our theme, or we can create a simple plugin to handle the contact form. Let’s just code this into the functions.php for simplicity sake.

对于这一部分,我们有两种选择,选择其中一种都可以。 我们可以通过我们主题的functions.php插入admin_post_*操作,也可以创建一个简单的插件来处理联系表单。 为了简单起见,我们将其编码到functions.php中。

Remember that we have our custom action contact_form in the form, so by rights, we will have these four hooks available to us:

请记住,我们在表单中有自定义操作contact_form ,因此按权利,我们将可以使用以下四个钩子:

  • admin_post_nopriv

    admin_post_nopriv

  • admin_post_nopriv_contact_form

    admin_post_nopriv_contact_form

  • admin_post

    admin_post

  • admin_post_contact_form

    admin_post_contact_form

Open up functions.php of your current theme and add these lines in:

打开当前主题的functions.php ,并在以下行中添加这些行:

function prefix_send_email_to_admin() {
    /**
     * At this point, $_GET/$_POST variable are available
     *
     * We can do our normal processing here
     */ 

    // Sanitize the POST field
    // Generate email content
    // Send to appropriate email
}
add_action( 'admin_post_nopriv_contact_form', 'prefix_send_email_to_admin` );
add_action( 'admin_post_contact_form', 'prefix_send_email_to_admin` );

Since we want to handle the form submission the same way no matter if the user is currently logged in or not, we point to the same callback function for both admin_post_nopriv_contact_form and admin_post_contact_form. The actual callback function, prefix_send_email_to_admin will be your main point to do the data processing.

由于无论用户当前是否登录,我们都希望以相同的方式处理表单提交,因此我们针对admin_post_nopriv_contact_formadmin_post_contact_form都指向相同的回调函数。 实际的回调函数prefix_send_email_to_admin将是您进行数据处理的重点。

结论 (Conclusion)

admin-post.php is a useful, hidden gem contained in the WordPress core. By utilizing it, we can keep the separation of concern between the actual template, and unrelated code that is not needed for display separated by hooking into the appropriate hooks for processing.

admin-post.php是WordPress核心中包含的一个有用的隐藏宝石。 通过利用它,我们可以将实际模板与显示不需要的无关代码分离,方法是将它们钩入适当的钩子进行处理。

Get the Right File Permissions in Your WordPress Site with our tutorial.

通过我们的教程在WordPress网站中获取正确的文件权限

翻译自: https://www.sitepoint.com/handling-post-requests-the-wordpress-way/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值