17

I tried to use a form with the following markup using the action admin-post.php

<form method='post' action='admin-post.php'>

I'm using the action hook suggested by Wordpress to proceed the $_POST parameters and it works fine. However after execution I got a blank page and no redirect back to the plugins page. Of course I could set a custom redirect with the referer, but is that the normal behaviour?

A Workaround is to use action="" and and getting the request in my normal plugin code.

4
  • 4
    If you use admin-post.php and admin_post action you need to redirect back to your plugin page.
    – cybmeta
    Feb 4, 2015 at 18:15
  • That information should be added to the codex. I wasn't sure about this. Feb 5, 2015 at 8:46
  • 1
    If you send the form to admin-post.php, admin.post.php is where the user go. Just see the content of that file to know that it doesn't print anything, just check the authentication cookie and run the functions hooked to admin_init first and admin_post later.
    – cybmeta
    Feb 5, 2015 at 8:59
  • 2
    wp_redirect does not work when posting forms with admin-post. It will give error that headers are already sent, so this seems to be a worthless method for posting a form and trying to redirect somewhere afterwards. Dec 2, 2016 at 7:26

3 Answers 3

26

Maybe a little late but I stumbled on this when I was having issues figuring it out so thought I would supply what I found out for future people.

I've found the basic principles are to have a hidden input named action and it's value being a custom set identifier. For example

<input name='action' type="hidden" value='custom_form_submit'>

With this input, and your forms action pointing to admin-post.php an action can be set. We set this action using admin_post_custom_form_submit.

To make things more complicated we can use a wp_nonce_field which I think is a basic security thingy. Basically it adds a random $_POST value. Fair enough.

Next we want to set our action like so:

add_action('admin_post_custom_form_submit','our_custom_form_function');

So when there is a form submitted to admin-post.php and there is an action value of custom_form_submit the function our_custom_form_function will be called! :D

function our_custom_form_function(){
    //print_r($_POST);
    //you can access $_POST, $GET and $_REQUEST values here. 
    wp_redirect(admin_url('admin.php?page=your_custom_page_where_form_is'));
   //apparently when finished, die(); is required. 
}

Now you say you get a white page. This is because we need to redirect back to our form. I've used a simple wp_redirect()

Hope this has helped :) I'm going to try and figure out how I can do some validation and give errors back to our redirect form. I think the simplest idea would be to make a $_GET value and find that on our page but it's not great is it?

I've also found that once submitted $_POST is cleared!! DX This is probably to do with the redirect. I'll have a google and see what I can find :d

Hope this has helped :)

UPDATE

I done some more work and realised the only real way to return values is to use the $_GET variable. This way you can re-enter any post values. Just don't forget to use urlencode()to ensure that special characters such as '@' and so on are included.

I had more than one page with what I was working on so I done 2 different redirects to the different pages and included the errors and so on. The checked for them above my form.

Another handy function. http_build_request() can turn arrays into 'url safe' arrays so that you can send them over $_GET requests etc.

5
  • Hi bro thanks this is working for me..! but one problem is there, how can i set error to admin.php?page=your_custom_page_where_form_is i did used add_settings_error() for display error but it not display any error because page is redirect..! can you please help me for that..? thank Sep 2, 2017 at 6:23
  • 1
    Hi @BhavikHirani I don't really use wordpress anymore but my guess would be you need to do your validation before the wp_redirect function call and have an if statement to say that your validation was passed before redirecting. Hope this helps?
    – bashleigh
    Sep 4, 2017 at 8:12
  • after form submission i want to show success message in 'admin.php?page=your_custom_page_where_form_is' how is it possible?
    – Rijo
    Mar 24, 2018 at 2:48
  • @Rijo tried echo?
    – bashleigh
    Mar 26, 2018 at 8:54
  • Each method has it's own use cases. This method, passes data in the URL via $_GET. This would be fine for some basic info, like maybe displaying their name or email, or to pass a ?success=true flag which triggers your success message. However, it will not work for returning large amounts of data from the form submission, use case, they submit the form and it returns data from an API.
    – Wade
    Jan 24, 2020 at 20:06
6

Before redirecting you can save any validation errors and post values into a transient. These values will persist after the url redirection.

This is exactly how WP core does it for the Settings API when returning errors.

So:

-validate form data

-store post data in transient with set_transient()

-store any errors in transient

-redirect to form output

-check for errors in transient

-load post values into form fields from transient

You could use a session or the Options API instead of a transient.

Now, I've been experimenting with various ways of handling form submissions both on the frontend and on the admin. I'm not sure admin_post_{action} is all that convenient because of the need to persist data and errors across the redirect. Using the init or admin_init hook to check for a form submission might be easier. You could also simply post your form back to the same page and process the form submission before the form is displayed.

1
  • Note: set_transient() has a max length of 172 chars. This is a plausible option if you don't or can't use GET variables and it isn't a lot of data. AFAIK, Wordpress doesn't use sessions (by default) so for a plugin, this may be inappropriate. Options API would be a terrible choice. -- The final option if you need to hit an API and return a large amount of data, is to POST to the site/page itself. -- The admin-post.php is limited and probably isn't the right choice if you need to return a large amount of data.
    – Wade
    Jan 24, 2020 at 20:14
4

The short answer is that you have to do all the work: save the user input in the database, check for errors or success, and redirect wherever you want when finished.

If you want to redirect to the form again you can use a field generated by wp_nonce() included in the $_POST array sent by your form: $_POST['_wp_http_referer']

Finally you can redirect and send a success or error message using wp_safe_redirect(), esc_url_raw() and add_query_arg().

add_action( 'admin_post_my-action', 'my_save_form_function' );
add_action( 'admin_post_nopriv_my-action', 'my_save_form_function' );
function my_save_form_function() {
    if ( ! empty( $_POST['_wp_http_referer'] ) ) {
        $form_url = esc_url_raw( wp_unslash( $_POST['_wp_http_referer'] ) );
    } else {
        $form_url = home_url( '/' );
    }
    if ( isset( $_POST['name'] )
        && isset( $_POST['description'] )
        && isset( $_POST['my-nonce'] )
        && wp_verify_nonce(
            sanitize_text_field( wp_unslash( $_POST['my-nonce'] ) ),
            'my-action'
        )
        ) {

        // Save your form data...

        //All  works fine ?
        wp_safe_redirect(
            esc_url_raw(
                add_query_arg( 'my_status', 'success', $form_url )
            )
        );
        exit();
    } else {
        wp_safe_redirect(
            esc_url_raw(
                add_query_arg( 'my_status', 'error', $form_url )
            )
        );
        exit();
    }
}
1
  • redirecting me to wp-admin/admin-post.php?my_status=success rather then the origin form page. Not working properly Jun 2, 2021 at 12:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.