Handling form submission in WordPress plugins

I’ve been using the Advanced Custom Fields (ACF) plugin for general form handling for some weeks on the front end and it has been very useful and quite nice to work with.

But I wanted to use a lighter approach for simple forms like unsubscribe or yes/no confirmation pages, because designing a form in the back end for this looks a bit overkill and I don’t necessarily need my form to create a new post after submission.

I wanted to decouple the presentation from the logic, so that meant keeping form handling in a plugin while managing the display aspect in my theme to keep things clean.

I found a tutorial about how to do this in the back end in a clean way but I couldn’t find anything related to the front end. I saw some references to the admin_post_$action action hook herehere, here and here but no documentation about this action in the WordPress Codex.

So here you go, first I had to create a function in the plugin that the theme can call to show the form (heavily inspired by ACF as you can see) :

function myplugin_unsubscribe_form($options = array())
    $defaults = array(
        'id' => false,
        'hash' => false,
        'submit_value' => __('Unsubscribe', 'myplugin')

    $options = array_merge($defaults, $options);

    echo '<form method="post" action="'.admin_url('admin-post.php').'">'."\n";
    echo '<input type="hidden" name="id" value="'.$options['id'].'" />'."\n";
    echo '<input type="hidden" name="hash" value="'.$options['hash'].'" />'."\n";
    echo '<input type="hidden" name="action" value="myplugin_unsubscribe" />'."\n";
    echo '<input type="submit" name="unsubscribe" value="'.$options['submit_value'].'">'."\n";
    echo '</form>'."\n";

Then in a page template from my theme I need to call this function to actually display the form  :

    'id' => $id,
    'hash' => $hash,
    'submit_value' => __("Unsubscribe from this newsletter", 'myplugin')

In this same file the logic for managing the display of the form and the message to be displayed after form submission can be handled as usual (using conditions on $_GET for example).

if (!isset($_GET['action'])) {
        'id' => $id,
        'hash' => $hash,
        'submit_value' => __("Unsubscribe from this newsletter", 'myplugin')
} else {
    switch ($_GET['action'])
        case 'success' :
            echo "Success";
        default :
            echo "Error";

And finally the logic is implemented in the plugin to handle the form submission :

function myplugin_unsubscribe_action()
    $id = $_POST['id'];
    $hash = $_POST['hash'];
    $nonce = $_REQUEST['_wpnonce'];

    if (!wp_verify_nonce($nonce, 'myplugin_unsubscribe') {
        die( 'Security check' );
    } else {
        // Do stuff here
        $action = "success"

        // Redirect to initial page
        wp_redirect(add_query_arg(array('action' => $action), $_POST['_wp_http_referer']));
add_action( 'admin_post_myplugin_unsubscribe', 'myplugin_unsubscribe_action' );

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s