I'm coding an external php script that will be called from ajax in one of my WP page.
I want this script to be able to use wordpress functions.
This is what I've done so far:
require_once( $_SERVER['DOCUMENT_ROOT'] . '/wp-load.php' );
this allows me to access $wpdb object. Good. But I also want to use is_email() function and perhaps other native WP functions.
Right now I'm getting "Call to undefined function is_email()..." Fatal error.
Any advice appreciated
You are doing it wrong. WP is glad to provide the requested functionality for you. You should declare the handler in your plugin/theme functions.php file and register a handler for wp_ajax_my_action (the example is taken from WP Codex):
<?php
add_action( 'wp_ajax_my_action', 'my_action_callback' );
function my_action_callback() {
global $wpdb; // this is how you get access to the database
$whatever = intval( $_POST['whatever'] );
$whatever += 10;
echo $whatever;
wp_die(); // this is required to terminate immediately
// and return a proper response
}
More info.
Perhaps not the most elegant way but at least it worked for me.
in functions.php
add_action( 'wp_enqueue_scripts', 'localize_scripts');
function localize_scripts() {
wp_localize_script('jquery', 'urls', array( 'ajaxurl' => admin_url('admin-ajax.php') ));
}
inside the javascript
$.ajax({
url: urls.ajaxurl,
data: {
'action':'my_function',
'otherData': someString //variable
},
cache: false,
success: function() {},
error: function() {}
});
and again in functions.php
function my_function() {
// The $_REQUEST contains all the data sent via ajax
if ( isset($_REQUEST) ) {
$someString = $_REQUEST['otherData'];
echo $someString;
// Always die in functions echoing ajax content
die();
}
}
add_action( 'wp_ajax_my_function', 'my_function' );
Related
First time posting to StackOverflow. (upvotes appreciated to help me get included in the community)
Despite being new to coding in general, I've been able to work out the following steps in Wordpress thanks to Zac Gordon's very helpful video https://youtu.be/Z0Jw226QKAM?t=216 and demo files https://github.com/zgordon/wordpress-ajax following the steps he outlines:
Pass Nonce and AJAX URL via wp_localize_script
Make AJAX call with Nonce and URL in JavaScript
Hook PHP AJAX Function into Wordpress AJAX Hooks
Use JavaScript to Handle AJAX Response
Although I am able to return the expected result with the AJAX response (which I can print to console) and I am now able to retrieve a value to pass to another function, I am unable to update the value in advance of passing it to other functions.
Based on other StackOverflow conversations (JQuery - Storing ajax response into global variable) I am thinking this is probably an issue with Asynchronous vs Synchronous AJAX calling. However I've further read that setting "async: false" should be avoided at all costs and seems to be deprecated at this point (and didn't help when I tried) so I'm trying to find the proper way to pass this variable from one function to another. Answers I read were not specific to Wordpress which left me at a loss for solving on my own.
The goal is fairly straightforward: get the $(window).height() using AJAX, store as a variable, pass variable into another function in PHP which transforms that variable and adjusts the height of a map Plugin (hook: storymap_heights ).
For starters: I'm currently just trying to get this to work with initial page load, but I would also be curious if it's possible to rerun the functions every time the browser window is resized?
The following code gets me close: I have to refresh twice for the global variable $heights {and/or "get_option( 'jsforwp_heights' )" } to update and properly set the "new" browser window size (so it seems to be storing the variable but not until after it runs through at least once before). The code is currently stored in a Wordpress Snippets plugin, but should work the same as being placed in Functions.php:
<?PHP
global $heights;
if ( null == $heights ) {
add_option( 'jsforwp_heights', 100 );
}
$heights = get_option( 'jsforwp_heights' );
function my_theme_scripts() {
wp_enqueue_script( 'my-great-script', get_template_directory_uri() . '/assets/js/my-great-script.js', array( 'jquery' ), '1.12.4', true );
wp_localize_script(
'my-great-script',
'jsforwp_globals',
[
'ajax_url' => admin_url('admin-ajax.php'),
'total_heights' => get_option('jsforwp_heights'),
'nonce' => wp_create_nonce('nonce_name')
]
);
}
add_action( 'wp_enqueue_scripts', 'my_theme_scripts' );
function screen_height_is(){
check_ajax_referer('nonce_name');
global $heights;
$heights = $_POST['height'];
update_option('jsforwp_heights',$heights);
// set_map_height($heights); //test
$response['success'] = true;
$response['height'] = $heights;
$response = json_encode($response);
echo $response;
wp_die();
}
add_action('wp_ajax_screen_height_is','screen_height_is',1);
add_action( 'wp_ajax_nopriv_screen_height_is', 'screen_height_is',1 );
function set_map_height(){
global $heights;
$testA = get_option('jsforwp_heights');
$testB = "px";
$height = $testA. $testB;
echo $height;
return $height;
}
add_filter('storymaps_heights','set_map_height',10);
//tests for function above
//function set_map_height($heights){
//$testA = '300'; //static option
//$testA = $heights; //works with same loading delay problem
//$testA = $response['height']; //doesn't work even if $response set as global
I have tried nesting the functions without success and calling the set_map_height($heights) from within the screen_height_is() function without success. I also have tried setting #Priority within add_action and add_filter (1 for add_action, 10 for add_filter) to try to get them to wait to run but this also does not seem correct.
The following code is stored in my js file: my-great-script.js:
jQuery(document).ready(function($){
var myResponse;
$.ajax({
type: 'post',
dataType: 'json',
url: jsforwp_globals.ajax_url,
async: false,
data: {
action : 'screen_height_is',
_ajax_nonce : jsforwp_globals.nonce,
width : $(window).width(),
height : $(window).height(),
screen_width : screen.width,
screen_height: screen.height
},
success: function( response ) {
// if( 'success' == response) {
if( response['success'] == true) {
alert("Something went right");
}
else {
alert("Something went wrong");
}
}
})
.done(function(response) {
console.log(response);
})
.fail(function(error) {
alert(error);
})
.always(function() {
console.log("complete");
});
});
Console log prints:
{height: "598", success: true}
complete
I am a little unclear if/how I should be modifying the Success callback to reach my overall goal? Or if the wp_enqueue_script() dependencies need to be modified?
In case this helps, the following filter in PHP hooks into the storymaps-core.php file:
add_filter('storymaps_heights','set_map_height',10);
Where the following wp_enqueue_script resides:
function storymap_external_resources() {
wp_enqueue_style( 'storymap-stylesheet', 'https://cdn.knightlab.com/libs/storymapjs/latest/css/storymap.css' );
wp_enqueue_script( 'storymap-javascript', 'https://cdn.knightlab.com/libs/storymapjs/latest/js/storymap-min.js', array(), '1.0.0', false );
}
add_action( 'wp_enqueue_scripts', 'storymap_external_resources' );
Any help on what to try next is much appreciated!
Struggling to pass through some php variables into my ajax handler function in functions.php
Example provided below doesn't work, probably has something to do with the hooks but I can't find any info on how to do this:
/*Unsubscribe*/
$test_variable = "derp";
function user_unsubscribe($test_variable){
echo json_encode($test_variable);
wp_die();
};
add_action('wp_ajax_user_unsubscribe', 'user_unsubscribe');
add_action('wp_ajax_nopriv_user_unsubscribe', 'user_unsubscribe');
Solved it with this solution: can I pass arguments to my function through add_action?
Working code solution is:
/*Unsubscribe*/
$test_variable = "derp";
function user_unsubscribe($test_variable){
echo json_encode($test_variable);
wp_die();
};
add_action('wp_ajax_user_unsubscribe', function() use ($test_variable){
user_unsubscribe($test_variable);
});
add_action('wp_ajax_nopriv_user_unsubscribe', function() use ($test_variable){
user_unsubscribe($test_variable);
});
You can pass that PHP variable in ajax data. Please check below files in which I had send the "test_variable" Value to Ajax Function from jQuery.
Jquery File Code
jQuery(document).ready(function($) {
$('#btn').on('click',function(){
$.ajax({
data: {action: 'get_listing_names','test': global.test_variable},
type: 'post',
url: global.ajax,
success: function(data) {
console.log(data);
}
});
});
});
Functions.php file Code.
<?php
/**
* Enqueue scripts and styles.
*
* #since 1.0.0
*/
function ja_global_enqueues() {
wp_enqueue_script(
'global',
get_template_directory_uri() . '/js/global.js',
array( 'jquery' ),
'1.0.0',
true
);
wp_localize_script(
'global',
'global',
array(
'ajax' => admin_url( 'admin-ajax.php' ),
'test_variable' => 'Test Value',
)
);
}
add_action( 'wp_enqueue_scripts', 'ja_global_enqueues' );
add_action('wp_ajax_nopriv_get_listing_names', 'ajax_listings');
add_action('wp_ajax_get_listing_names', 'ajax_listings');
function ajax_listings() {
$test_variable = $_POST['test_variable'];
wp_send_json_success( $test_variable );
}
The prefered way to pass variables to ajax is to add them to the request and read them from $_GET or $_POST official documentation
If you need other variables you'll either have to use globals or call a extra function.
favorite
Struggling to pass through some php variables into my ajax handler function in functions.php
Example provided below doesn't work, probably has something to do with the hooks but I can't find any info on how to do this:
function user_unsubscribe(){
$test_variable = get_test_variable();
echo json_encode($test_variable);
wp_die();
};
add_action('wp_ajax_user_unsubscribe', 'user_unsubscribe');
add_action('wp_ajax_nopriv_user_unsubscribe', 'user_unsubscribe');
function get_test_variable() {
// here get/fetch your variable;
/*Unsubscribe*/
$test_variable = "derp";
return $test_variable;
}
I want to call /home/***/public_html/subdomains/busuioc/wp-content/themes/scalia/json_gallery_data.php
the content of json_gallery_data.php is:
global $wpdb;
$programs = $wpdb->get_results("SELECT * FROM program_tv");
$tv=array();
foreach ( $programs as $program){
$tv[]=$program->day;
}
echo json_encode($tv);
the ajax file is:
jQuery(document).ready(function(){
loadData();
});
var loadData=function(){
jQuery.ajax({
type:"POST",
url: 'site.com/wp-content/themes/scalia/json_gallery_data.php'
}).done(function(data){
var videos=JSON.parse(data);
for(var i in videos){
alert(videos[i]);
}
});
};
$wpdb won't be defined since you're bypassing wordpress, you'll have to use wordpress' ajax api to have access to it.
put your code block inside a function, and place it in the functions.php file of your theme (if you want to keep it in a separate file, include it in the functions.php file)
function my_ajax_handler(){
global $wpdb;
$programs = $wpdb->get_results("SELECT * FROM program_tv");
$tv=array();
foreach ( $programs as $program)
{
$tv[]=$program->day;
}
echo json_encode($tv);
wp_die();
}
after that you have to "register" it with wordpress' ajax api, and you do it like this
add_action( 'wp_ajax_call_my_ajax_handler', 'my_ajax_handler' );
add_action( 'wp_ajax_nopriv_call_my_ajax_handler', 'my_ajax_handler' );
wp ajax (action)
wp_ajax_nopriv_(action)
now, the file you're going to call in your ajax request is site.tld/wp-admin/admin-ajax.php. you can hardcode it, but that wouldn't be the best thing to do. ideally you should store it in a javascript variable, and wordpress has a handy function to do exactly that. put the below in the callback function that you're using to enqueue your scripts/styles
wp_enqueue_script( 'my-ajax-script', get_stylesheet_directory_uri() . '/path/to/script.js', array('jquery') );
wp_localize_script( 'my-ajax-script', 'my_ajax_object', array( 'ajax_url' => admin_url( 'admin-ajax.php' ) ) );
wp_localize_script
now all you have to do is to modify your ajax call to include the ajax trigger we registered before,
jQuery.ajax({
type:"POST",
url: my_ajax_object.ajax_url,
data: { 'action': 'call_my_ajax_handler' }
})
notice how call_my_ajax_handler is the same thing we "registered" before.
assuming that there aren't any errors, you should see the expected result.
none of the code has been tested.
take a look at the AJAX in Plugins codex entry as well.
I need to set a WC()->set inside a php jquery .get function. What do I need to do inside of the php file to get access to the WC(). Right now it is telling me that WC is undefined.
This is inside my cart.php file that displays the cart and shows two radio buttons for a delivery options.
Here is the script that handles the RB change (I've simplified just to get the function to execute the reload upon return from the php query):
<script>
jQuery(document).ready(function($){
$("#myid").change(function(){
console.log("RB Changed!");
passed_variable = "1";
$.get('http://www.example.com/test.php',
{pass_var: passed_variable},
function(data, status) {
console.log("returned");
location.reload();
});
});
});
</script>
And here is the PHP query:
<?php
global $woocommerce;
echo "START<BR>";
$temp = $_GET["pass_var"];
WC()->session->set('_delivery_loading', $temp);
// or
$woocommerce->session->set('_delivery_loading', $temp);
echo "DONE[" . $temp . "]";
?>
Why do you need to call test.php? If you use a wp_ajax_$action callback you will be within the WP framework and WC() will be loaded. here's an example cobbled together from the codex and jQuery .ajax().
Enqueue the script you will be making the ajax calls from:
function so_34107959_enqueue_script(){
wp_enqueue_script( 'so_34107959_script', plugins_url( '/js/so_34107959.js' , __FILE__ ), '1.0b', array('wc-add-to-cart'), true );
}
add_action( 'wp_enqueue_scripts', 'so_34107959_enqueue_script' );
Note that the wc-add-to-cart script is a dependency. I'm only doing that so we can use WooCommerce's localized script variables. If you need to use this somewhere that the add to cart script isn't used then you will need to wp_localize_script() and pass in the admin ajax url yourself.
Your script file so_34107959.js:
jQuery(document).ready(function($){
$("#myid").change(function(){
var passed_var = "1";
$.ajax({
url: wc_add_to_cart_params.ajax_url, // here's the ajax url from WooCommerce
data: { action: "add_foobar", pass_var: passed_var } // the action must match up to wp_ajax_$action
})
.done(function( data ) {
if ( console && console.log ) {
// should return either success or fail
console.log( data );
}
});
});
});
And finally this code is the callback for your ajax "action":
function so_34107959_ajax_add_foobar() {
$temp = isset( $_REQUEST["pass_var"] ) ? $_REQUEST["pass_var"] : '';
if( $test ){
WC()->session->set('_delivery_loading', $temp);
echo 'success';
} else {
echo 'fail';
}
die();
}
add_action( 'wp_ajax_add_foobar', 'so_34107959_ajax_add_foobar' );
add_action( 'wp_ajax_nopriv_add_foobar', 'so_34107959_ajax_add_foobar' );
Untested, so watch out for typos.
Further explanations:
The PHP code assumes that you are writing a plugin. You could cheat and put it in your theme's functions.php but I think the theme should be kept for presentation and any functionality should be in plugins.
The codex has this explanation for the wp_ajax_$action hook:
This hook allows you to create custom handlers for your own custom AJAX requests. The wp_ajax_ hook follows the format "wp_ajax_$youraction", where $youraction is your AJAX request's 'action' property.
This means that if you pass an "action" to the "data" in your .ajax() that same action will wind up as the tail end of your wp_ajax_$youraction callback.
In my example therefore here's the data bit from the .ajax() script:
data: { action: "add_foobar", pass_var: passed_var }
The action is "add_foobar". It can be whatever.
Then you append that action "add_foobar" to the end of "wp_ajax_" so that add_action() looks like:
add_action( 'wp_ajax_add_foobar', 'so_34107959_ajax_add_foobar' );
This is for the admin/logged in users. The "nopriv" in:
add_action( 'wp_ajax_add_foobar', 'so_34107959_ajax_add_foobar' );
means that the ajax hook is available to non-logged in users.
Lastly, so_34107959_ajax_add_foobar() is the the server-side function that will handle your ajax request.
I am trying to check if a username is available in wordpress by using ajax with a php script backend, however am unsure of how to do this correctly.
In the checkusername.php script, I include WordPress's user.php like so:
require_once("../wp-includes/user.php");
I call username_exists( $_POST["username"] ) and am greeted with the following error:
Call to undefined function get_user_by() in ...\user.php on line 1613
Note I abbreviated the location. If I include pluggable.php I get a similar error but for
Class 'WP_User' not found in ...\pluggable.php on line 152
Honestly I don't really know how I am supposed to be correctly utilizing the user.php file outside of wordpress pagetemplates so if someone could help me that would be great.
If you are using ajax in WordPress, you don't need to do it "outside" of WordPress. WordPress has it's own filter hook system which allows for ajax callback functions to be run while having FULL access to all of WordPress's functionality.
Have a look at this:
https://codex.wordpress.org/Plugin_API/Action_Reference/wp_ajax_%28action%29
Here is a complete example of how to set up an ajax callback properly in WordPress:
PHP Code (place in plugin or functions.php file of theme)
//First enqueue your javascript in WordPress
function your_prefix_enqueue_scripts(){
//Enqueue your Javascript (this assumes your javascript file is located in your plugin in an "includes/js" directory)
wp_enqueue_script( 'your_unique_js_name', plugins_url('js/yourjavascriptfile.js', dirname(__FILE__) ), array( 'jquery' ) );
//OR (simpler but not recommended)
wp_enqueue_script( 'your_unique_js_name', 'http://domain.com/myjavascriptfile.js', array( 'jquery' ) );
//Here we create a javascript object variable called "youruniquejs_vars". We can access any variable in the array using youruniquejs_vars.name_of_sub_variable
wp_localize_script( 'your_unique_js_name', 'youruniquejs_vars',
array(
//To use this variable in javascript use "youruniquejs_vars.ajaxurl"
'ajaxurl' => admin_url( 'admin-ajax.php' ),
)
);
}
add_action( 'wp_enqueue_scripts', 'your_prefix_enqueue_scripts' );
//This is your Ajax callback function
function your_ajax_callback_function_name(){
//Get the post data
$username = $_POST["username"];
//Run any WordPress function you want in this ajax callback
if ( username_exists( $username ) ){
$array_we_send_back = array( 'message' => __( 'This user exists', 'textdomain' ) );
}
else{
$array_we_send_back = array( 'message' => __( 'This user does not exist', 'textdomain' ) );
}
//Make sure to json encode the output because that's what it is expecting
echo json_encode( $array_we_send_back );
//Make sure you die when finished doing ajax output.
die();
}
add_action( 'wp_ajax_' . 'your_ajax_callback_function_name', 'your_ajax_callback_function_name' );
add_action( 'wp_ajax_nopriv_' . 'your_ajax_callback_function_name', 'your_ajax_callback_function_name' );
And then this goes in your javascript file:
jQuery(document).ready(function($){
/**
* When your ajax trigger is clicked
*
*/
$( document ).on( 'click', '.my-button', function(event){
event.preventDefault();
// Use ajax to do something...
var postData = {
action: 'your_ajax_callback_function_name',
username: 'test_username_1',
}
//Ajax load more posts
$.ajax({
type: "POST",
data: postData,
dataType:"json",
url: youruniquejs_vars.ajaxurl,
//This fires when the ajax 'comes back' and it is valid json
success: function (response) {
alert( response.message );
}
//This fires when the ajax 'comes back' and it isn't valid json
}).fail(function (data) {
console.log(data);
});
});
});
do not include files manually, use standard wordpress Ajax API
https://codex.wordpress.org/AJAX_in_Plugins
If you need access to WordPress function you will have to include wp-load.php
require_once("wp-contents/wp-load.php");
But this is not best practice, you shouldn't load the file directly.
Instead you can follow instructions on how to use WordPress ajax API as in the answer of kkarpieszuk
(https://codex.wordpress.org/AJAX_in_Plugins)
These answers are fine if you are writing a plugin that is to be distributed out into the world, and you really need it to play nice with the rest of the WordPress landscape, and you don't care about performance. If you have a lot of plugins in your site... especially large ones like BuddyPress, then running ajax calls through the standard WP ajax pipeline can be very inefficient due to the fact that all of the plugins get loaded and processed, and the init routine gets called on all of the plugins for every ajax call. Coming from a non-WordPress world, this seems crazy to me. 99% of ajax calls don't need all of that infrastructure to be set up to do what they need to do.
To avoid this, set up your ajax php page to use the SHORTINIT code, and load the required files in the header. ( See also here: https://wordpress.stackexchange.com/questions/173002/how-declare-ajax-functions-ussing-shortinit )
For access to wpdb, get_current_user, and check_ajax_referer, I used the following the top of my ajax page:
N.B. our install has wordpress in the /wp folder, NOT the root folder! Your path names may be different
the file below might be something like /plugins/myplugin/my_ajax_event_handler.php
...and it would be called directly from $.ajax in the client javascript
<?php
define('SHORTINIT', true);
//IMPORTANT: Change with the correct path to wp-load.php in your installation
$path = $_SERVER['DOCUMENT_ROOT'];
include_once $path . '/wp/wp-load.php';
include_once $path . '/wp/wp-includes/wp-db.php';
include_once $path . '/wp/wp-includes/formatting.php';
include_once $path . '/wp/wp-includes/capabilities.php';
include_once $path . '/wp/wp-includes/session.php';
include_once $path . '/wp/wp-includes/user.php';
include_once $path . '/wp/wp-includes/meta.php';
include_once $path . '/wp/wp-includes/pluggable.php';
wp_cookie_constants( );
wp_plugin_directory_constants();
my_ajax_event_handler();
function my_ajax_event_handler() {
global $wpdb;
// A nonce should be passed in from the client in the post field "security"
check_ajax_referer( 'my_ajax_event_handler', 'security' );
... do all my cool ajax stuff ...
die();
}
?>
Note that I'm working in a large corporate environment, and expect to be forced to do work to upgrade my code whenever we upgrade WordPress. This method works for me, but the normal wp_ajax_ way is definitely safer.