Categories: php, jquery, ajax, wordpress, api

Wordpress ajax call where a class instance that relies on Google Sheets API can't authenticate

1 answer

Through a Wordpress plugin I have a form that collects user values and compares them against values stored in a Google Sheet.

Setup: A PHP file for a class has a construct that connects to Google Client and assigns a variable for the class methods to use. These methods get data and compare data. When a user fills out and submits the form, an AJAX call posts the values to a php file where a new instance of this class is initiated and form values are compared against Google Sheet values via class methods.

Issue: This all works as expected until I involve Wordpress. When I set the ajax url to admin-ajax.php and hook in with wp_ajax_{my_function}/ wp_ajax_nopriv_{my_function} it doesn't work. After some digging, this is the issue I found in the Wordpress debug log:

PHP Fatal error:  Uncaught InvalidArgumentException: file "google-api/credentials.json" does not exist in wordpress\wp-content\plugins\myplugin\google-api\php-client-2.4.0\src\Google\Client.php:904 Stack trace: #0 wordpress\wp-content\plugins\myplugin\my-class.php(37): Google_Client->setAuthConfig('google-api/cred...') #1 wordpress\wp-content\plugins\myplugin\my-class.php\my-php-file.php(25): MyObject->__construct() #2wordpress\wp-content\plugins\myplugin\FileContainingMyAjaxHookFunction.php: require_once('my-class.php') #3 C:\xampp\htdocs\wordpress\wp-includes\class-wp-hook.php(288): MyAddActionsObject->MyAjaxHookFunction('') #4 wordpress\wp-includes\class-wp-hook.php(312): WP_Hook->apply_filters('', Array) #5 wordpress\wp-includes\plugin.php(478): WP_Hook->do_action(Array) #6 C in C:\xampp\htdocs\wordpress\wp-content\plugins\myplugin\google-api\php-client-2.4.0\src\Google\Client.php on line 904 

I don't have any issues when I call the php file directly in the url of my AJAX call. This leads me to believe it's the way I'm handling AJAX via Wordpress hooks.

My class looks like this:

require_once 'google-api/php-client-2.4.0/vendor/autoload.php';  class My_Object {   protected static $googleService;        public function __construct() {     $client = new \Google_Client();     $client->setApplicationName ('My Name');     $client->setScopes([\Google_Service_Sheets::SPREADSHEETS]);     $client->setAccessType('offline');     $client->setAuthConfig('google-api/credentials.json');      self::$googleService = new Google_Service_Sheets($client);   }    public static function get_sheet_data() {     $service = self::$googleService;   }    public static function do_stuff() {...} }  

The Ajax:

$.ajax( {         type: "POST",         url: myAjax.ajaxurl,         data: {            action: 'MyAjaxHookFunction',            myDataOne: myDataOne,            myDataTwo: myDataTwo         },          success: function(results) {             $("#MyId").append(results);             jQuery( document.body ).trigger( 'post-load' );         }     }); 


require_once plugin_dir_path( dirname( __FILE__ ) ) . 'my-php-file.php'; die(); 

Note: I tried adding the class instance in MyAjaxHookFunction but that didn't work.

My php file:

require_once ('my-class.php'); $data = new My_Object; $data::dostuff(); 

Notes: I'm working locally via XAMPP. The Google PHP API is included in the plugin directory. I'm using PHP as I don't want the data stored in Google Sheets viewable.

Any help or insight appreciated. Thanks.

All answers to this question, which has the identifier 61215172

The best answer:

After a sleep and looking at this again, the solution seemed straitghtforward.

Why there was a problem: AJAX is being executed through admin-ajax.php in the wp-include directory. My class construct refers to a credentials file relative to the location of class file itself. I needed to specify a path that could be used from anywhere in the directory.

To solve I edited the url parameter in $client->setAuthConfig('url') in the class construct:

  require_once 'google-api/php-client-2.4.0/vendor/autoload.php';    class My_Object {     protected static $googleService;          public function __construct() {       $client = new \Google_Client();       $client->setApplicationName ('My Name');       $client->setScopes([\Google_Service_Sheets::SPREADSHEETS]);       $client->setAccessType('offline');       $client->setAuthConfig( plugin_dir_path(__FILE__) . 'google-api/credentials.json');        self::$googleService = new Google_Service_Sheets($client);     }      public static function get_sheet_data() {       $service = self::$googleService;     }      public static function do_stuff() {...}   }  

Now it works as expected.

What was learned: always use a Wordpress directory path function, like plugin_dir_path(), when specifying paths in plugin files.

If there are any issues with my implementation or better ways of doing things, I look forward to hearing them.

Last questions

how do i remove the switch on my home screen?
how to edit the JS date and time to update atuomatically?
How to utilize data stored in a multidimensional array
Powermockito not mocking URL constructor in URI.toURL() method
Android Bluetooth LE Scanner only scans when phone's Location is turned on in some devices
docker wordpress container can't connect to mysql container
How can I declare a number in java that is more than 64-bits? [duplicate]
Optaplanner solutionClass entityCollectionProperty should never return null error when simple JSON object passed to controller
Anylogic, get the time a pedestrain is in a queue
How do I fix this syntax issue with my .flex file?
Optimizing query in PHP
How to find the highest number of a column and print two columns of that row in R?
Ideas on “Error: Type is referenced as an interface from”?
JCIFS SmbFile.exists() and SmbFile.isDirectory() return false when it exists and I can listFiles()
PHP total order
Laravel booking system design
neural net - undefined column selected
How to indicate y axis does not start from 0 in ggplot?
Fragments in backStack
Spinner how to change the data