I wrote a plugin to hit an API and display results on a page. When I was testing, every time I hit "preview", the plugin would hit the API and retrieve the most recent data. Now that the plugin is live, when I navigate to the live page, no calls are being made to the API.
Through research I believe this is a caching issue, since we want real time data, we would like that every time a user navigates to the page, the plugin fires off to the API and the most recent values are returned.
Here is a snippet of my code:
function get_count(){
//get response from api
$request = wp_remote_get('');
if(is_wp_error($request)){
return false;
}
//get the body from the response
$body= json_decode(wp_remote_retrieve_body($request));
//parse the body and get the count attribute
$statistic=($body->payload->count);
return '<div id="value" class="number">'. $statistic . '</div>';
}
add_shortcode('real_time_count','get_count');
How can I make this execute every time a user navigates to a page that has this shortcode?
I wrote a plugin to hit an API and display results on a page. When I was testing, every time I hit "preview", the plugin would hit the API and retrieve the most recent data. Now that the plugin is live, when I navigate to the live page, no calls are being made to the API.
Through research I believe this is a caching issue, since we want real time data, we would like that every time a user navigates to the page, the plugin fires off to the API and the most recent values are returned.
Here is a snippet of my code:
function get_count(){
//get response from api
$request = wp_remote_get('https://myapi/count');
if(is_wp_error($request)){
return false;
}
//get the body from the response
$body= json_decode(wp_remote_retrieve_body($request));
//parse the body and get the count attribute
$statistic=($body->payload->count);
return '<div id="value" class="number">'. $statistic . '</div>';
}
add_shortcode('real_time_count','get_count');
How can I make this execute every time a user navigates to a page that has this shortcode?
Share Improve this question edited Mar 1, 2019 at 18:33 rudtek 6,4035 gold badges30 silver badges52 bronze badges asked Mar 1, 2019 at 14:55 user2821694user2821694 211 silver badge2 bronze badges 3- 1 If you use curl instead of remote_get, do you have the same experience? – MikeNGarrett Commented Mar 1, 2019 at 15:09
- @MikeNGarrett The question says that the request to the API isn't being made, not that there was anything wrong with the result of the request. This would happen if they had some sort of caching, which the question also mentions. – Jacob Peattie Commented Mar 1, 2019 at 15:45
- Oh. Different question entirely. Sorry about that. – MikeNGarrett Commented Mar 1, 2019 at 16:14
2 Answers
Reset to default 3If you want to make sure the data bypasses any front-end caching, you should use AJAX to request the data and print it on the page.
What I'd suggest is keeping your shortcode, but using AJAX to update it but creating a REST API endpoint. To do this you would abstract away the API request into its own function, and then have the shortcode and API response both use that function:
/**
* Function for retrieving the count from the API.
*/
function wpse_330377_get_count() {
$request = wp_remote_get( 'https://myapi/count' );
if( is_wp_error( $request ) ) {
return false;
}
$body = json_decode( wp_remote_retrieve_body( $request ) );
$statistic = $body->payload->count;
return $statistic;
}
/**
* Shortcode for outputting the count.
*/
function wpse_330377_count_shortcode() {
$statistic = wpse_330377_get_count();
return '<div id="value" class="number">'. $statistic . '</div>';
}
add_shortcode( 'real_time_count', 'wpse_330377_count_shortcode' );
/**
* REST API endpoint for getting the count.
*/
function wpse_330377_register_rest_route() {
register_rest_route(
'wpse_330377',
'count',
[
'method' => 'GET',
'callback' => 'wpse_330377_get_count'
]
);
}
add_action( 'rest_api_init', 'wpse_330377_register_rest_route' );
Now you can use JavaScript to send a request to the new API endpoint, /wp-json/wpse_330377/count
, which will give us the new value that we can use to update the #value
div.
Create a JavaScript file like this, in your theme or plugin:
jQuery.get(
{
url: wpse330377.apiUrl,
success: function( data ) {
jQuery( '#value' ).html( data );
}
}
);
And then enqueue it and pass it the correct URL:
function wpse_330377_enqueue_script() {
wp_enqueue_script( 'wpse_330377_count', 'URL TO SCRIPT GOES HERE', [ 'jquery' ], null, true );
wp_localize_script(
'wpse_330377_count',
'wpse330377',
[
'apiUrl' => rest_url( 'wpse_330377/count' ),
]
);
}
add_action( 'wp_enqueue_scripts', 'wpse_330377_enqueue_script' );
Just replace URL TO SCRIPT GOES HERE
with the actual URL. Use get_theme_file_uri()
to get the URL for a file in your theme, or plugins_url()
if it's in a plugin.
PS: Note that I've used wpse_330377
as a prefix and namespace in many places. You should use a prefix like this to prevent conflicts with WordPress and other themes or plugins. Ideally it would be something specific to your project.
I missed the last part of your question :facepalm:
In this case, it depends on what your caching mechanism is on your site. Some plugins, like W3 Total Cache, allow you to mark sections of a page as non-cacheable. If this isn't an option, then Jacob's answer about using AJAX is probably the way to go. This way, you can request the data "fresh" every time.
Not what you're looking for below
You should check a couple of things. The only caching that might affect wp_remote_get
would be on the response side of things, since WordPress does not cache anything it gets back in the WP_Http
class's request
method.
As Mike commented, do you get the same "empty" response using curl
? Try this on the command line if you have curl
available:
curl https://myapi/count
Does the response look the same as doing
curl https://myapi/count?foo=134134234234
?
If the responses differ, then your myapi
server may be caching the response. If not, you need to figure out why the remote server is not sending back the expected response.
Debugging Further
If it's not caching, you should do something like this:
// In your wp-config.php
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', WP_DEBUG );
In your function above:
if ( is_wp_error( $request ) ) {
error_log( $request->get_error_message() );
}
Now, run your script, and then check the contents of /wp-content/debug.log
to see if there are any errors related to your request.
If your certificate for myapi
isn't "valid" (i.e. signed by a CA), you should look at the arg sslverify
for wp_remote_get
:
@type bool $sslverify Whether to verify SSL for the request. Default true.
Which can be modified like so:
wp_remote_get( 'https://myapi/count`, [ 'sslverify' => false ] );
If it is caching
You can use the current time to bust the cache of each request, like so:
$request = wp_remote_get( 'https://myapi/count?time=' . time() );