POST request and Transients API in WordPress

POST request and Transients API in WordPress

Created:16 Apr 2018 22:25:52 , in  Web development

It is striking how often basic scripting of POST request can cause a real headache to a person who is not somewhat familiar with certain assumptions WordPress makes on how these requests should be handled. Even more confusion can ensue in cases when a feedback has to be given once the request has been processed and user redirected. Providing the feedback is a very frequent requirement which to be fulfilled requires preserving data between consecutive page loads more often than not.

Normally sessions or cookies are used to preserve information for the next and further HTTP request. WordPress does not use the former, though. The latter, on the other hand, offer very limited data storage capacity, hence are hardly suitable for many usual cases.

Fortunately, WordPress comes equipped with a mechanism called Transients. It is primarily used to store cached data in wp_options database table but also lends itself to preserving data between HTTP requests.

In this article I look briefly at the flow of POST request in WordPress and a way of preserving data between HTTP requests using its Transients API.

Flow of POST request in WordPress

Elevated difficulty with regards to dealing with POST requests in WordPress arises due to the fact that, all of them are supposed to be sent to a script living in admin/admin-post.php file. This is not what most of us are used to or sometimes even familiar with.

Moving on though, once HTML form data is received, the script decides what to do with it on the basis of contents of "action" parameter.

If, for example, "action" parameter is "execute_me", the script will try to call a function hooked to admin_post_execute_me action for each logged in user and admin_post_nopriv_execute_me action for user who is not. It is up to you to define the function and hook it properly. If noting is attached to the hooks, your form won't be processed. So, carry out this step carefully.

Giving feedback

Suppose you have defined and hooked your function(s). If you don't want for your user to get stuck at admin/admin-post.php after parameters provided through the form are processed, you should redirect them to some page ( sometimes back to the the same one the form is on). You user will certainly expect some feedback on how the submission went upon landing there. In order to provide it you might need to save and then, in the following request, restore some data. Transients API allows you to do both of these fairly easily.

Using Transient API

Saving and loading data into the database is straightforward. You use set_transient($transient,$value) and get_transient($transient) for these respectively.

Also, once you are done with your data you call delete_transient($transient) to rid of it.

$transient is a string. $value can be a regular variable, an array or an object.

A concrete take

To give you something to play with, below is a PHP class which uses exactly the ideas described above. It is called WPPostRequest and consists of just three methods. In its display_form() a tiny HTML form gets assembled. The form consists of two hidden and two visible controls. The hidden fields pass "action" and "redirect_to" parameters to the backend. The visible fields are a select control which gives user three choices and a submit button.

Once the form is sent, handle_post_request() is executed by script in wp-admin/admin-post.php. The function saves some data from the form in the database using save_transient(), redirects user back to the page from which they submitted the form and exits the script. I added some extra user input cleaning functions, you might not know about, in there. The functions in question are: sanitize_text_field, wp_http_validate_url and wp_sanitize_redirect.

Once the the user is redirected, they will see the original HTML form but also the choice they have made using the select control. The choice is loaded from the database using get_transient(). When that piece of data is no longer needed it is deleted using delete_transient().

In __construct() a shortcode called wppr_display_html_form gets added. It allows you to add the form by placing [wppr_display_html_form] as a part of contents of a page or post on the admin side. Also, handle_post_request() gets hooked to admin_post_wppr_action and admin_post_nopriv_wppr_action actions there.

WPPostRequest PHP class


/*
  Class: WPPostRequest 
  Description: Perform POST request in WordPress and give feedback
  Author: Sylwester Wojnowski
  WWW: wojnowski.net.pl
*/
class WPPostRequest{

  const TRANSIENT = 'wppr_transient';
  const OPTION_VALUES = array(
    'key1' => 'Value 1',
    'key2' => 'Value 2',
    'key3' => 'Value 3'
  );

  function __construct(){
    # add a shortcode so that it is easy to add the form in any post or page
    add_shortcode('wppr_display_html_form', array(&$this,'display_form'));
    # both logged in and not logged in user should be able to send our HTML form
    add_action('admin_post_wppr_action', array(&$this,'handle_post_request' ));
    add_action('admin_post_nopriv_wppr_action', array(&$this,'handle_post_request' ));

  }

  /*
    Display form and show feedback
  */
  function display_form(){
    # see whether there is a saved transient
    $transient = get_transient(self::TRANSIENT);
    # if yes, get its value 
    $value = ($transient !== false) ? sanitize_text_field($transient) : '';
?>
  <?php if($value): ?>
    <?php echo '<p>You selected: <strong>' . esc_html($value) . '</strong> !</p>'; ?>
  <?php else: ?>
    <p>Please, select a value:</p>  
  <?php endif ?>

  <form action="<?php echo home_url('/wp-admin/admin-post.php') ?>" method="post">
  <input type="hidden" name="action" value="wppr_action">
  <input type="hidden" name="redirect_to" value="<?php echo esc_url(get_permalink()) ?>">
  <p>
  <select name="wppr_value"> 
    <?php foreach(self::OPTION_VALUES as $k => $v ): ?>
      <?php $selected = ($value === $v) ? 'selected' : '' ?> 
      <option value="<?php echo esc_html($k) ?>" <?php echo $selected ?>>
        <?php echo esc_html($v) ?>
      </option>
    <?php endforeach ?>
  </select>
  </p>
  <p>  
  <input type="submit" value="Submit">
  </p>
</form>
<?php
    # if transient present, delete it
    if($transient !== false){
      delete_transient(self::TRANSIENT);
    }  
  } 

  /*
    Callback executed once form has been submitted  
  */
  function handle_post_request(){
  
    # set default option
    $key = 'key1';
    $redirect_to = home_url('/');
    
    # do basic user input check 
    if(isset($_POST['wppr_value'])){
      $key = sanitize_text_field($_POST['wppr_value']);  
    } 
    
    # check redirection link
    if( isset($_POST['redirect_to']) && wp_http_validate_url($_POST['redirect_to']) ){
      $redirect_to = wp_sanitize_redirect($_POST['redirect_to']);
    }
    
    # use a transient to preserve required data for later
    set_transient(self::TRANSIENT,self::OPTION_VALUES[$key]);
    # redirect and exit
    wp_redirect( $redirect_to );
    exit;
  }
}
# instantiate the the class
new WPPostRequest();

Making WPPostRequest work

To play with WPPostRequest, copy and paste it into your theme's functions.php file, add [wppr_display_html_form] shortcode and navigate to the page / post you've just finished editing.

Final thoughts

For a purpose described in this article you might want to use options rather than transients API. I chose transients.

One convenient thing about Transients in WordPress is, they can be given expiration time and auto-deleted by WordPress.

Like for options, WordPress takes care of some rough edges with regards to saving and loading data. It serializes it if needed, it will also escapes it routinely.

This post was updated on 16 Apr 2018 23:36:16

Tags:  php ,  wordpress 


Author, Copyright and citation

Author

Sylwester Wojnowski

Author of the above article, Sylwester Wojnowski, is sWWW admin and owner.He enjoys doing Maths and studying algorithms, writing code in scripting and command languages, Thrash Metal music and playing electric guitar.

Copyrights

©Copyright, 2018 Sylwester Wojnowski. This article may not be reproduced or published as a whole or in parts without permission from the author. If you share it, please give author credit and do not remove embedded links.

Computer code, if present in the article, is excluded from the above and licensed under GPLv3.

Citation

Cite this article as:

Wojnowski, Sylwester. "POST request and Transients API in WordPress." From sWWW - Code For The Web . https://wojnowski.net.pl//main/index/post-request-and-transients-api-in-wordpress