I've pored over other threads' WordPress AJAX questions with 400 errors, but I just can't seem to get this right.
I am in WordPress trying to implement some AJAX. Right now I have dummy functions in place just to learn about the AJAX functionality, but I can't get them to work.
On my page template, I have this Javascript at the bottom of the page:
<script>
var ajax_url = "<?php echo admin_url( 'admin-ajax.php' ); ?>";
var data = { action : 'bp_check_user_role' };
jQuery.post(ajax_url, data, function (success) { console.log(success); });
</script>
In my Code Snippets plugin, I have this PHP:
function bp_check_user_role() {
echo "Hi!";
die();
}
add_action('wp_ajax_bp_check_user_role', 'bp_check_user_role');
add_action('wp_ajax_nopriv_bp_check_user_role', 'bp_check_user_role');
I feel like I'm doing these two steps properly, but when I load the page the code doesn't work and I get this (I've scrubbed {mysite}, but it is correct):
jquery.js?ver=1.12.4:4 POST https://{mysite}.com/wp-admin/admin-ajax.php 400 ()
Any ideas or obvious mistakes I am making? I just can't seem to crack this one :(
Threads I've read in addition to referring to the WordPress Codex:
https://wordpress.stackexchange.com/questions/220661/use-ajax-without-a-plugin
Wordpress Ajax always returns 0
As I've pointed in my comment:
Visit
https://{mysite}.com/wp-admin/admin-ajax.php?action=bp_check_user_role
and see if you see the "Hi!" text.
Why visit that URL?
To verify that your AJAX 'action' is registered (properly) and that the AJAX response is also as you expected.
Additional Note
If you look at the code in wp-admin/admin-ajax.php, you'd see these:
if ( is_user_logged_in() ) {
// If no action is registered, return a Bad Request response.
if ( ! has_action( 'wp_ajax_' . $_REQUEST['action'] ) ) {
wp_die( '0', 400 );
}
...
do_action( 'wp_ajax_' . $_REQUEST['action'] );
} else {
// If no action is registered, return a Bad Request response.
if ( ! has_action( 'wp_ajax_nopriv_' . $_REQUEST['action'] ) ) {
wp_die( '0', 400 );
}
...
do_action( 'wp_ajax_nopriv_' . $_REQUEST['action'] );
}
So as you can see, it says // If no action is registered, return a Bad Request response., and therefore, if your AJAX JavaScript callback receives a 400 Bad Request error/response, then your AJAX 'action' is likely not registered, or that the PHP callback for the 'action' did not get called because the 'action' was registered after the do_action() call.
That may not always be the case; however, it can be a very good "first-aid" in troubleshooting AJAX issues.
Related
My goal is to return a message to my web-page, where it is to be displayed, but instead of just the message, the value returned contains the message and html code for an error page!
Here is the Symfony bundle action routing and function definition:
/**
* #Route("/Utilities/getMessages/{callSign}/{loginDateTime}",
* defaults={"callSign"="","loginDateTime"=""})
*
* #return: json string.
*
*/
public function getMessagesAction( $callSign, $loginDateTime ) { ... }
I am using the following code to return a message result to an ajax call:
Server-Side PHP code that is called by an Ajax call ...
$message = 'Some message to be displayed.';
// Return to the page and display the message ...
return new Response( $message ); // Inspecting $message shows only
// 'Some message to be displayed.'
Client-Side JavaScript code that calls the above code and receives the response:
$.ajax( { // Send form data to the same page that the page came from
type: 'POST',
data: data,
cache: false,
async: true,
contentType: false,
enctype: 'multipart/form-data',
processData: false
} )
.done( function( data, textStatus, jqXHR ) { ... } // Inspecting data
// shows more than
// 'Some ...
.fail( function( jqXHR, textStatus, errorThrown ) { ... }
When breakpoints are set at the return new Response( $message ); and first executable line in the .done(...) function, the PHP script execution gets to the breakpoint at the return new Response( $message ); statement without any errors and I can see that the parameter's value is 'Some message to be displayed.', as expected, but when paused at the .done() function's first line, the data parameter's value is:
Some message to be 'displayed.<!DOCTYPE html><html>...</html>!
Where, if the html code is placed in a file and loaded into the browser it looks somewhat like this:
Whoops, looks like something went wrong.
1/1 FatalErrorException in debug-eval(1) : eval()'d code line 1:
Parse Error: syntax error, unexpected ')'
in debug-eval(1) : eval()'d code line 1
An obvious error message, but my code isn't using any eval() statements that could fail and the execution got to the Response statement without any errors. Is this a bug in the Symfony Response statement method/function? If not, how can I find out what is really happening, so I can fix it?
Follow-Up
Changing the server-side code to encode a json string and then decoding it on the client-side doesn't help.
Server-Side PHP code:
// Return to the login page and display the message ...
// $message'value => '{ "message":"' . $message . '"}';
$message = json_encode( [ 'message' => $message ] );
return new Response( $message );
Client-Side Javascript:
***unchaged***
In this case I'm still inspecting the data parameter, but it now now contain the json encoded message AND the html error page code. Feeding this to the JSON.parse( data ); statement to convert the json data to an javaScript object causes the javaScript to freeze. This isn't a json issue, the problem of the html code appended to the end of my message still is happening either way.
Thank you
It's not a very clear error message but it sounds like your error is coming from Xdebug, and not PHP.
You can see a similar issue here.
I would check your "Watches" tab in the PHPStorm debug tab, and also from PHPStorm go to Run > View Breakpoints and remove all of them. To be sure you could also deactivate XDebug temporarily (via php.ini settings) to confirm that the problem disappears.
Try returning a new JsonResponse($json) instead of new Response($json).
As in:
use Symfony\Component\HttpFoundation\JsonResponse;
// ...
return new JsonResponse(['message' => $message]);
If you really (and I mean really) want to return a Response for whatever reason, you can also do:
$response = new Response(json_encode(['message' => $message]);
$response->headers->set('Content-Type', 'application/json');
return $response;
Bear in mind that I have never tried the last alternative, because JsonResponse has always worked for me. Also, JsonResponse extends Response class, so if you need anything from Response class, you can get it in JsonResponse.
The last response example is attached to this answer because of this Symfony Documentation.
I'm trying to figure out how Ajax and Wordpress plugins work, but it seems to be pretty badly documented. Ideally what I want is:
The plugin gets it own Ajax url to use, this is defined globally.
The plugin can handle Ajax requests
I understand that there are two actions that are used for this. One for logged in users and one for users without an account or privileges. However, I just want to create an Ajax endpoint for a form.
I'm not looking for code snippets, just need to be pointed in the write direction as to Wordpress Plugins and Ajax handling.
I implemented below own AJAX functionality in functions.php, Just try this in plugin,
functions.php :
function prefix_ajax_delete_search() {
global $wpdb;
$user_id = get_current_user_id();
$wpdb->delete('sf_save_search', array('id' => $_POST['tid']) );
wp_die();
}
add_action( 'wp_ajax_delete_search', 'prefix_ajax_delete_search' );
Script.js:
function deleteSearch( tid) {
var url = window.location.href;
jQuery.post(
ajaxurl,
{
'action': 'delete_search',
'tid': tid,
},
function(response){
location.reload();
}
);
}
I have a website which loads a RSS news feed http://www.tagesschau.de/xml/rss2
I want to check every 60 seconds if the RSS feed has been updated. If it has changed it should reload the RSS feed. With Ajax I thought it would work great, though I am stuck here:
<script type="text/javascript" src="../js/jquery.ajax-cross-origin.min.js"></script>
<script type="text/javascript">
function checkRSS() {
$.ajax({
crossOrigin: true,
type: 'GET',
proxy: "../php/proxy.php",
url: "http://www.tagesschau.de/xml/rss2",
dataType: "xml",
success: function (xml) {
//console.log(xml);
},
error: function(xml) {
console.log(xml);
}
});
}
setInterval("checkRSS()", 60000);
</script>
(I commented the success event console.log to see if Ajax would trigger the success or error event. It triggered the error event.)
In the console I get status: 200, readyState: 4 and statusText: "success".
Does anybody know why the error event is triggered? I checked the url through http://jsonlint.com. It does load the list but gives me an error. Is this the problem?
Ajax-Cross-Origin plugin: http://www.ajax-cross-origin.com/how.html#js-what-is-this-plugin
EDIT
I added a proxy php file from the Ajax-Cross-Origin plugin (and added its link in the Ajax code above):
<?php
$url = (isset($_GET['url'])) ? $_GET['url'] : false;
if(!$url) exit;
$referer = (isset($_SERVER['HTTP_REFERER'])) ? strtolower($_SERVER['HTTP_REFERER']) : false;
$is_allowed = $referer && strpos($referer, strtolower($_SERVER['SERVER_NAME'])) !== false;
$string = ($is_allowed) ? utf8_encode(file_get_contents($url)) : 'You are not allowed to use this proxy!';
$json = json_encode($string);
$callback = (isset($_GET['callback'])) ? $_GET['callback'] : false;
if($callback){
$jsonp = "$callback($json)";
header('Content-Type: application/javascript');
echo $jsonp;
exit;
}
echo $json;
?>
Maybe a stupid question, but should I change HTTP_REFERER and SERVER_NAME into something?
What happens now is that the success event is triggered -YES!- but the outcome of its log contains nothing more then " ".
Cross Site Scripting policies will make this tricky... your best bet is probably to use a 3rd party API such as Superfeedr or Google Feed API.
The benefit of this is that they will handle the load from you and will still be able to retrieve updates from the original feed pretty quickly.
While reading other similar questions I've learned that to send a javascript value to PHP variable I need to use AJAX. That's what I've done so far:
function onCursorChanged(e, data) {
$.post('familytree.php', {id: data.context.id});
<?php
if (isset($_POST['id'])) {
$id = $_POST['id'];
}
else {
$id = $individualid;
}
?>
}
The problem is that when I check if id is posted it always goes to else statement (id is always equal to individualid). However, when I change my code to this:
function onCursorChanged(e, data) {
$.post('familytree.php', {id: data.context.id,
success: function (msg){
alert('success') },
error: function (err){
alert(err.responseText)}
});
<?php
if (isset($_POST['id'])) {
$id = $_POST['id'];
}
else {
$id = $individualid;
}
?>
}
EDIT: the code above is mixed incorrectly because of a lot of experimenting I've been doing. The original code:
<script type="text/javascript">
function onCursorChanged(e, data) {
$.post('familytree.php', {id: data.context.id});
}
</script>
<?php
if (isset($_POST['id'])) {
$id = $_POST['id'];
}
else {
$id = $individualid;
}
$this->displayLeafEditForm ($_SESSION['username'], $id, $this->getParents($id));
Thanks to all the answers I realised that id is not set that's why I can't get the value in php. But I don'y understand why because data.context.id is the id of the item clicked and set after each click.
I get the message that says 'success'. Any idea why can't I get my variable posted?
The big problem here is that you mixing PHP and JavaScript incorrectly. You are expecting $_POST['id'] to be set in the JavaScript before it goes to the client. But by the time the JavaScript reaches the client, the PHP processing is already complete.
This means that when the $.post() happens, the server has already decided whether if (isset($_POST['id'])) is true. The server sends the output (the JavaScript) on to the client, and then no more PHP processing will happen.
Also, you are passing id, success, and error as data, which is almost certainly not what you want. You want this:
$.post('familytree.php',
{id: data.context.id},
success: function (msg){
alert('success')
},
error: function (err){
alert(err.responseText)
}
);
The AJAX success function cares whether the asynchronous call occurred without error. The fact that you even reached if (isset(...)) (and didn't set any error code eg. with header(...)) means that the AJAX call succeeded.
If isset is returning false, you need to look closer at the information that your AJAX call is actually sending to the PHP. Try putting in print_r($_POST) to see what post values you're actually getting.
I am trying to learn how to process AJAX requests in Wordpress the correct way. To do this I am adapting this tutorial to create a super simple AJAX request to place the ID of a post (from a link) into my page content.
The Logic
When the #our-work a links are clicked [js]
Get the post ID (from the data-id attribute) & store it as postID variable [js]
Pass postID via an AJAX (using the WP's admin-ajax.php file) [js]
The example_ajax_request function will pick up the ID & simply echo it [php]
If successful, append the server response to the #hero div.
I realise this has no benefit but once I have that working I will amend the function to serve a real purpose.
My Code
Here is a copy of the function I have created in the plugins folder:
wp_enqueue_script( 'my-ajax-request', plugin_dir_url( __FILE__ ) . 'acl-plugin.js', array( 'jquery' ) );
wp_localize_script( 'my-ajax-request', 'MyAjax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) );
function example_ajax_request() {
if ( isset($_REQUEST) ) {
$postID = $_REQUEST['postID'];
echo $postID;
}
die();
}
add_action( 'wp_ajax_nopriv_example_ajax_request', 'example_ajax_request' );
And here is a copy of the JS file
jQuery(document).ready(function($) {
$('#our-work a').click( function() {
var postID = $(this).attr("data-id");
$.ajax({
url: MyAjax.ajaxurl,
data: {
'action':'example_ajax_request',
'postID' : postID
},
success:function(data) {
$('#hero').append( "Well this seems to work" + data );
},
error: function(errorThrown){
console.log("This has thrown an error:" + errorThrown);
}
});
return false;
});
});
The Problem
Upon clicking the link the JS does fire but yields the following response:
<div id="hero">
Well this seems to work 0
</div>
Using an alert I know the ID is being picked up before the AJAX request. So the problem is in my function. To find out more, I (temporarily) tweaked WP's admin-ajax.php file, so that I could find out which die(); was yielding the response of "0".
It is the very last one in the file which I thought wouldn't fire as I have a die(); command in my own function. Can someone please point out where I am going wrong?
This is one of those rare times I can proudly say... there isn't any problem here!
The reason the server is returning with 0 is because I was logged in! The wp_ajax_nopriv_example_ajax_request is only for users who are not logged in. After logging out this works fine.
So if you are looking to do the same thing, just make sure you have both actions below the function:
add_action( 'wp_ajax_example_ajax_request', 'example_ajax_request' );
add_action( 'wp_ajax_nopriv_example_ajax_request', 'example_ajax_request' );