Handling form submissions in WordPress with admin-post.php

Draft

Overview

In this post we’ll learn how to use admin-post.php and the associated admin_post_ actions to process form submissions from a theme or plugin.

WordPress provides this mechanism for handling general GET and POST requests in your theme or plugin, and despite the word “admin” throughout, it’s intended for both front and back-end use.

The Actions

We’ll begin by choosing an action to hook onto, which will be passed from our form. Let’s call it mf_form. These actions will point to a function to handle the request, we’ll call that mf_form_function. We use add_action to map our hooks to their functions, like so:

add_action( 'admin_post_mf_form', 'mf_form_function' );
add_action( 'admin_post_nopriv_mf_form', 'mf_form_function' );

There are two actions here for separating logged-in and not logged-in visitors with the addition of nopriv_ in the action tag.

The Form

To render our form we’ll create a simple Shortcode. We’ll use admin_url() to generate the URL to admin-post.php, and wp_nonce_field() to generate a nonce. We’ll also add a hidden action field to pass the mf_form action we hooked in the last step.

function mf_form_shortcode() {

    $action_url   = admin_url( 'admin-post.php' );
    $nonce_fields = wp_nonce_field( 'mf_form_example', 'mf_form_example_nonce', true, false );

    $form  = '<form action="' . $action_url . '" method="post">';
    $form .= $nonce_fields;
    $form .= '<input type="hidden" name="action" value="mf_form">';
    $form .= '<input type="text" name="data">';
    $form .= '<input type="submit" value="Submit">';
    $form .= '</form>';

    return $form;

}
add_shortcode( 'mf_form', 'mf_form_shortcode' );

Now when we insert the Shortcode [mf_form] in a page or post, we’ll see our form rendered.

The Function

The next piece is the mf_form_function function mapped to our action. This is where the form is processed and a response is generated. In this example we’ll use the POST / Redirect / GET pattern.

function mf_form_function() {
    if( isset( $_POST['mf_form_example_nonce'] )
    && wp_verify_nonce( $_POST['mf_form_example_nonce'], 'mf_form_example' ) ){ 

        wp_safe_redirect( $_POST['_wp_http_referer'] . '?milo_form_submitted=true', 302 );      
    }
    die();
}