How do i best handle custom plugin page actions?

I’m constantly running into the same annoyance, so i thought i’d see if there’s any ideas or experience out there…

I’ve created a plugin that uses it’s own admin page. It has to. Now that i sorted out the WP_List_Table() stuff, i must say it’s great…but….

Custom plugin pages always load as admin.php?page=... unless i want to load them from the plugin directory directly, which i don’t. Now if i do an ‘action’ from that page, i need to process that somehow and then redirect back to the page without the action parameter. No matter if i do a GET or POST, really.

On all it’s internal pages WP does this on the same page, it checks if there’s an action, if so processes it and then redirects to itself without the action. This is possible, because on these pages the admin-header hasn’t been loaded, yet.

If you try doing it on your own page, though, half the admin interface has already been sent to the browser, so a redirect isn’t possible anymore. Clearly, the solution is to POST/GET directly to another page, load the WP framework on that, do the processing and then redirect back to the original page…but…that’s a bit annoying, because…my original page is loaded via a callback, so it runs within a method of my class. That’s beautiful.

If i load a separate page, i have to manually include wp-load.php and am outside of my class, which is annoying, and in my particular case bugs me especially, because i’m only instanciating my plugin class anonymously so that no-one can access it from the outside.

So after this long story…did anyone come up with a good solution to load another page via a callback without having the whole admin interface already setup around it?

(I know of a workaround…i can hook a function into load-.... that checks for the action parameter and does the processing and redirect. But i’m wondering if there’s a better way.)

Thanks.

3

As a rule of thumb, you should use a POST request for most actions, to make sure they are not executed by accident. But it is also a good practice to redirect to a normal page after a POST request, to prevent duplicate execution when the user refreshes the page.

So the flow is like this:

  1. Your plugin page with a POST form, which submits to
  2. A page that handles the request, which redirects to
  3. Your plugin page, which shows the result of the action

The middle page doesn’t have to be your plugin page. This means that you can use the “generic POST handler” that was included three years ago, the 'admin_action_' . $_REQUEST['action'] hook in admin.php.

An example user is the Akismet plugin. If you want to use it reliably, you have to submit to admin.php directly, not to another page that happens to include admin.php.

Here is a very basic example of how to use it:

add_action( 'admin_action_wpse10500', 'wpse10500_admin_action' );
function wpse10500_admin_action()
{
    // Do your stuff here

    wp_redirect( $_SERVER['HTTP_REFERER'] );
    exit();
}

add_action( 'admin_menu', 'wpse10500_admin_menu' );
function wpse10500_admin_menu()
{
    add_management_page( 'WPSE 10500 Test page', 'WPSE 10500 Test page', 'administrator', 'wpse10500', 'wpse10500_do_page' );
}

function wpse10500_do_page()
{
?>
<form method="POST" action="<?php echo admin_url( 'admin.php' ); ?>">
    <input type="hidden" name="action" value="wpse10500" />
    <input type="submit" value="Do it!" />
</form>
<?php
}

Leave a Comment