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
// ...
}
}
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
// ...
}
}
Share
Improve this question
edited Aug 21, 2020 at 0:04
armadadrive
asked Aug 20, 2020 at 17:28
armadadrivearmadadrive
2395 silver badges14 bronze badges
12
|
Show 7 more comments
1 Answer
Reset to default 0As 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.
$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. – armadadrive Commented Aug 20, 2020 at 18:07$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 thewp_enqueue_script
is called among other things. – armadadrive Commented Aug 20, 2020 at 18:13My_Example_Plugin::Ajax_method()
and so it exists in a different context from when the shortcode instantiates the plugin. – armadadrive Commented Aug 20, 2020 at 18:18wp_localize_script()
does is output a script tag into the HTML that sets some JavaScript variables. – Jacob Peattie Commented Aug 21, 2020 at 12:23