0

When trying to get data within an instance of a plugin, all of the PHP methods defined in our plugin class file can "see" the data that was just set for a certain property.

However, when we create a PHP method that responds to an AJAX post request from the JavaScript file in our plugin, all of a sudden that property is just empty as if it's never been set.

Accessing it from any other method works fine, so it leads me to believe that the AJAX-callable method is seeing a different context of $this which hasn't had the property set yet.

Is this likely the case? Or is something else afoot?


Edited for clarity:

The data in question is set at run-time via a parameter in the shortcode that kickstarts the main functionality. So it doesn't exist until the shortcode is executed which got me wondering if the way AJAX calls the method exists in a different context than the plugin object created by WordPress on page load.


Edited to add code snippets (just the relevant stuff, these are NOT complete):

// From WP template file:

// This is well-formed and on the other end the plugin can print_r() the 
// unserialized $args just fine
<?php echo do_shortcode('[cptgm ' . serialize($args) . ']'); ?>
// From plugin class file:
private query_args;

public function get_query_args() {
  if (!empty($this->query_args)) {
    return $this->query_args;
  }
  return false;
}

public function set_query_args($newArgs) {
  if (empty($newArgs)) {
    return false;
  }
  $this->query_args = $newArgs;
}

public function render_map_shortcode($atts = [], $content = null, $shortcode_tag = '') {

  // We know from doing a print_r() of $this->get_query_args immediately after
  // this line that the property is set and can be accessed
  $this->set_query_args(unserialize($atts[0]));
  $this->render_map();
}

// This is the method called via AJAX and is the only time in the plugin
// that we seem to have an issue. When called via AJAX, we can't print_r()
// here, but the return value is an empty array ONLY when we replace a hard-coded
// $args with $this->get_query_args(), which works everywhere else
public function get_data_from_custom_fields() {
  $return_data = [];
  $args = $this->get_query_args();

  // If we hard-code the $args, the WP_Query works fine and echos JSON
  // as a response to the JS file just fine. Only when we try and use
  // $this->get_query_args(); does the plugin end up echoing back $return_data
  // as an empty array (the way it was initialized above)

  // This is what led us to believe that, in the AJAX context, 
  // $this->get_query_args(); didn't seem to be supplying the $args we knew where 
  // there when the same getter was called from other methods
  $wp_query = new WP_Query($args);
  // ... echo/return results from $wp_query as JSON to the calling JS file
}
// From the plugin's JS file:
function cptgmRenderMap() {
  console.log('[CPTGM] Rendering map...');

  cptgmData = {
    'action': 'get_data_from_custom_fields'
  }

  $.post(ajax_object.ajax_url, cptgmData, function(response) {
    var parsedResponse = JSON.parse(response);
    // Setup map markers, etc. EXCEPT that the return JSON is now empty
    // ...
  }
}
12
  • That doesn't sound right. What is the property you are looking at? Is it something that requires data that wouldn't necessarily be available in an AJAX callback?
    – vancoder
    Commented Aug 20, 2020 at 17:43
  • We're syncing Google Map markers to an archive page for a custom post type. When the data set has been filtered down in the template (via conditionals checking for $_POST requests to the archive-* file), we need the JS in the plugin to only render map markers for the filtered set. We've been trying to use the page's current $args, passed via a serialized parameter in the shortcode and set as $this->query_args, so the JS can use AJAX and request its own data from our PHP that matches the set, but it sees $this->query_args as empty even though all other non-AJAX methods can see it. Commented Aug 20, 2020 at 18:07
  • To clarify, when the plugin's main functionality is instantiated via shortcode, it immediately sets $this->query_args using the attributes passed via the shortcode params. All the methods in the class can see those query args, too. But not if the data is requested via the method exposed as an AJAX action to the plugin's JS file. I thought perhaps there was a race condition, but before the JS is even enqueued in WP (though it had earlier been registered), the object sets the property immediately upon the shortcode callback running. THEN the wp_enqueue_script is called among other things. Commented Aug 20, 2020 at 18:13
  • The data we want is set at runtime by the shortcode params. I'm just surprised that an AJAX call to a defined method in the plugin can't see it, which got me thinking that maybe the way that the JS and WP together call the method is more like a static thing like My_Example_Plugin::Ajax_method() and so it exists in a different context from when the shortcode instantiates the plugin. Commented Aug 20, 2020 at 18:18
  • 1
    That’s not how PHP works. I would step back from worrying about WordPress and just think about how PHP works. A PHP application runs from scratch for every web request. There’s no sharing of sessions, or persistence, or anything like that. A PHP application is just a script that runs once for each request. It has no “state”. When it comes to WordPress, literally the only thing that wp_localize_script() does is output a script tag into the HTML that sets some JavaScript variables. Commented Aug 21, 2020 at 12:23

1 Answer 1

0

As per confirmation from @Jacob Peattie, my understanding is now this (if it is helpful to future readers).

AJAX calls to a WordPress plugin method exist in a totally separate context (separate requests) from the object instance created when a WordPress plugin's PHP files are interpreted when a page is loaded.

Therefore, a property that is given a specific value only during runtime (for example, $this->foo), while being visible during a given session, is not guaranteed to be visible to an AJAX call. The AJAX call accesses the object's property as it is set on new object instantiation OR if it were set or changed via and during the AJAX call.

To make a dynamic data change visible between JS and PHP files, even if belonging to the same plugin package, likely requires another storage method.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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