Submitting form via admin-post.php and handling errors

I have a custom form I’m adding to a page by using a page template (I don’t want to use a plugin for specific reasons). I’m submitting this form using admin-post.php. Inside functions.php I have my function to process the form, which is working. I can display the validation errors on the blank admin-post.php but obviously that isn’t want I want.

So here are my questions.

  • Am I supposed to just do normal redirects back to my form page?
    Something like wp_redirect( '/my-page/',302);?

  • How do I display my errors on the page that has the form?

  • On success, how do I replace the form with a success message?

I feel like I’m missing a crucial piece of the puzzle…

Here is a stripped down version of the form.

<form action="<?php echo esc_url(admin_url('admin-post.php')); ?>" method="post">
    <label for="tos_agree">
        <input type="checkbox" name="tos_agree" id="tos_agree" <?php if ($_POST['tos_agree']){ echo 'checked="checked"'; } ?> />
        Some text for the checkbox
    </label>

    <button type="submit" name="agree" value="I Agree">I Agree</button>

    <input name="action" type="hidden" value="updated_tos_agree" />
</form>

And My Function

function updated_tos_agree_submit() {

    function form_submit() {
        $error = new WP_Error();

        if (!$_POST['tos_agree']){
            $error->add('notchecked','You must agree to the Terms.');
        }

        return $error;
    }

    $result = form_submit();

    if (is_wp_error($result)) {
        echo '<ul>';
            echo '<li>' . implode( '</li><li>', $result->get_error_messages() ) . '</li>';
        echo '</ul>';
    }else{
        // Update User Meta
    }

    die();
}

add_action('admin_post_nopriv_updated_tos_agree', 'updated_tos_agree_submit');
add_action('admin_post_updated_tos_agree', 'updated_tos_agree_submit');

1 Answer
1

Am I supposed to just do normal redirects back to my form page?
Something like wp_redirect( '/my-page/', 302 );?

Yes.

How do I display my errors on the page that has the form?

Well, there are various ways, including:

  1. Passing an error code as a query string in the redirect URL: example.com/my-page/?my_form_error=tos_agree_empty. Then in your form/template, you could do something like echo $messages[ $_GET['my_form_error'] ]; where $messages is an array of error messages. (Note: In actual implementation, you should sanitize the query value.)

  2. Saving the error in a transient — a temporary database option.

On success, how do I replace the form with a success message?

Pretty much the same as with the above question. So you can:

  1. Include a “success” status in the redirect URL: example.com/my-page/?my_form_success=1. Then in your form/template, you can do something like if ( ! empty( $_GET['my_form_success'] ) ) { echo 'Success.'; } else { /* Display the form. */ }.

  2. Or once again, use the transient API to save (and also retrieve) the “success” status.

And you might find it useful by reading the article here which explains in-depth about handling form submissions using the admin-post.php, plus it also talks about AJAX (admin-ajax.php) which is really good in that no page reloads would be necessary in submitting the form. However, you should instead use the REST API to create a custom endpoint for your form submissions. 🙂

So I hope this (new) answer helps you and you can see here an example of using the transient API for persisting the form validation errors and submitted data to be used after being redirected from admin-post.php. I also hope the linked answer helps, which gives an example of handling the form submission using template_redirect which is fired on the same page — the admin_post_ hooks are fired on a different page in the admin (wp-admin) side of the site.

Leave a Comment