2

In a WordPress theme I am displaying info from an external JSON API. How can I cache this data to improve page load times.

I have a jQuery function

var url = 'http://my.api.com/'
$.getJSON(url)
  .done( function(data) {
    #display this data
  })
  .fail( function( jqXHR, textStatus, error) {
    #handle errors
  });

Does jQuery provide a way to cache these requests? Or should I be handling this within WordPress somehow (perhaps writing the response to a JSON file on the server)?

Brooke.
  • 3,691
  • 13
  • 49
  • 80
Andy Harvey
  • 12,333
  • 17
  • 93
  • 185
  • Have you read this post - http://stackoverflow.com/questions/17379312/cache-json-response ? – verisimilitude Feb 16 '14 at 03:50
  • thanks verisimilitude, I had seen something similar, but this is a useful post nonetheless. As my API response will be the same for all users (i.e., no variables are passed) I wonder whether server side caching would be a better option? What do you think? – Andy Harvey Feb 16 '14 at 03:57
  • If the response is similar for all users, then server side caching would definitely be a better option. – verisimilitude Feb 16 '14 at 04:08
  • any thoughts on the best way to do this within wordpress? – Andy Harvey Feb 16 '14 at 04:09

1 Answers1

7

Depending on the API and the context in which calls are made, you can use the server to complete these API calls rather than requiring the client to do it. Doing the former means you can utilise caching through the database, but will mean a little more strain on the server as it's the one now completing all of the requests.

This may only really be worthwhile if it's not user-specific information. That said, I'm a pretty big proponent of server-side caching of anything involving an external web service.

You'll probably want to leverage some of WordPress' built-in functionality, specifically including:

WP_Http This is WordPress' nifty built-in HTTP library which you can use to talk to the API.

Transients API Again - super nifty. Lets you store and retrieve self-expiring data to and from the local database.

A quick implementation (untested, please let me know if there are issues) is as follows:

define( 'HOURS', 60 * 60 );

function get_api_info( ) {

    global $apiInfo; // Check if it's in the runtime cache (saves database calls)
    if( empty($apiInfo) ) $apiInfo = get_transient('api_info'); // Check database (saves expensive HTTP requests)
    if( !empty($apiInfo) ) return $apiInfo;

    $response = wp_remote_get('http://my.api.com');
    $data = wp_remote_retrieve_body($response);

    if( empty($data) ) return false;

    $apiInfo = json_decode($data); // Load data into runtime cache
    set_transient( 'api_info', $apiInfo, 12 * HOURS ); // Store in database for up to 12 hours

    return $apiInfo;
}

Then, you just need to call get_api_info() anywhere in your code to retrieve the data you need. If you call the function multiple times in the same request/script, it will still only yell out to the database once. If you call the function in multiple requests within a 12 hour period, it will only send the API request once.

Talk about efficiency!

Of course I'd also recommend having a class implementation for this, so you can use instance variables rather than globals to store data, but that's just getting nitpicky.

Hope that helps!

adomnom
  • 564
  • 2
  • 9
  • thanks adomnom, this is exactly what I'm looking for. Do you know what is the max size that can be stored in a database field in this way? I have implemented your code above, and by checking the database I can see that the api response is being written to the correct option key, but I am unable to display this on the page? I've tried `echo get_api_info`. What am I doing wrong? – Andy Harvey Feb 16 '14 at 06:38
  • ignore my previous comment regarding the display error. A stupid mistake on my part. This is perfect, thank you! – Andy Harvey Feb 16 '14 at 07:55
  • any info on max field size is still appreciated. – Andy Harvey Feb 16 '14 at 07:56
  • Max field size for a transient is dependent upon your database schema, though by default (unless you've changed it), it's set to be a [LONGTEXT](http://dev.mysql.com/doc/refman/5.0/en/string-type-overview.html) type, which allows for up to 4GB. – adomnom Aug 18 '14 at 07:08