1

I am attempting to create a Plugin with a single shortcode that takes a param to identify which field to grab from my JSON API response.

The API returns multiple values, which I am attempting to be able to break out. For example:

[user_link type="url"]

would expose just the url, while

[user_link type="user_name"]

would expose just the name.

All of this should only hit the API once, not twice.

I attempted to set it my plugin file to look like this:

$api_response = null;

function get_user_info($type) {
  if($api_response === null) {
     ... make api reqest
     $api_response = api request data;
     return $api_response[$type];
  } else {
    return $api_response[$type];
  }
} 
add_shortcode( "user_link", "get_user_info" );

This still results in multiple API requests, one per shortcode I add. I believe this is happening for one of two reasons. Either the variable $api_response is getting cleared, or the shortcodes all run at the same time, and the variable is not set by the time the next one runs.

Is my approach here completely off? Is there a way to accomplish this? I am attempting to expose each piece of data separately to give the end user the ability to display and style the data as they would like.

7
  • My suggestion would be to periodically query your API automatically, maybe with a cron, store the response, and then have your shortcode retrieve the appropriate value from your stored copy of the response. Jun 26 '19 at 1:11
  • @JacobPeattie Thank you for your quick response. Unfortunately, this needs to run at page load, and the response is per user which passes a cookie to the server to get send back data specific to that user.
    – Connor
    Jun 26 '19 at 1:14
  • 1
    @Connor, how about using using the transients API?
    – Sally CJ
    Jun 26 '19 at 1:42
  • 1
    You do know that in PHP, variables are local unless declared global? Jun 26 '19 at 2:46
  • 1
    And sorry, I think I misunderstood something when I suggested the transients API - I thought the data needs to be temporarily persistent (across different page loads) - and if it doesn't need to (or persistent only on the same page load), you can use the WordPress Object Cache instead of transients, which as you said, might be overkill for what you're trying to do.
    – Sally CJ
    Jun 26 '19 at 3:40
0

The issue here is variable scoping. You're trying to access a global variable locally.

// Global scope.
$api_response = null;

function get_user_info( $type ) {
    // Local scope.    

    if ( $api_response === null ) {
        // make api reqest.
        // $api_response = api request data;
        return $api_response[ $type ];
    } else {
        return $api_response[ $type ];
    }
}
add_shortcode( 'user_link', 'get_user_info' );

Add global $api_response to the top of your function would solve your issue, however using global variables is generally frowned upon and you should consider another solution like transients (as mentioned in the comments).

An example of how to add transients to your function would be:

function get_user_info( $type ) {
    $user_id      = get_current_user_id();
    $api_response = get_transient( "prefix_api_response_$user_id" );

    if ( ! $api_response ) {
        // make api request.
        $api_response = api_request_data();

        // Save response for 1 day.
        set_transient( "prefix_api_response_$user_id", $api_response, DAY_IN_SECONDS );
    }

    return $api_response[ $type ];
}
2
  • Utilizing the transient API indeed got me to what I needed to get to. Thank you for your help. Regarding variable scoping, does declaring $api_response = null; at the top of the file not make the variable accessible to the whole file? I tried global $api_response = null;, but that produced a syntax error until I took the null out. At any rate, I was unable to get that going. Can you not scope a variable just to the single file you are working in?
    – Connor
    Jun 27 '19 at 12:32
  • The global statement just tells the script where to look for that variable. Any value assignment must happen after that. You can't scope a variable to a file. If you assign it outside a function it's global and can be accessed anywhere in the script thereafter. I think OOP would be perfect for this problem. You could create a singleton class to handle this.
    – ngearing
    Jun 27 '19 at 23:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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