ajax/json call in WordPress ends up in malformed JSON - php

I'm making an ajax call in a meta box and returning some very simple data. However, it keeps throwing an error:
parsererror
SyntaxError: JSON.parse: unexpected non-whitespace character after JSON data
Here's the ajax call:
uid = new Date().getTime();
appReq = jQuery.ajax({
type : 'post',
dataType : 'json',
url : 'admin-ajax.php',
data : { action : 'get_app_sidebars', post_id : currentApp, uid : uid }
});
appReq.done(function(data){
if(data.widgetNum > 0 && data.widgetName != '' && data.widgetBase != '') {
alert(data);
}
else {
// do something here
}
});
appReq.fail(function(jqXHR, textStatus, errorThrown){
alert(textStatus + '\n' + errorThrown);
});
And here's the php:
function get_app_sidebars(){
// get the meta for a custom post type
$meta = $this->get_app_meta($_REQUEST['post_id']);
$result['widgetNum'] = $meta['num_widgets'];
$result['widgetName'] = $meta['widget_name'];
$result['widgetBase'] = $meta['widget_base'];
$result = json_encode($result);
echo $result;
}
The problem comes in when I get the data back:
{"widgetNum":"6","widgetName":"Custom Sidebars","widgetBase":"my-custom-sidebars"}0
Ok, that "0" at the end is in the response when I look at this in firebug. This is driving me nuts, and I can't figure out WTF is going on with the JSON as it's being sent to the browser. If I trim the 0 and run it through jsonlint, it passes.

I'd suggest using wp_send_json_success, as it takes care of everything (json encoding, echo and die()):
function get_app_sidebars()
{
$meta = $this->get_app_meta($_REQUEST['post_id']);
if( $meta )
{
$result['widgetNum'] = $meta['num_widgets'];
$result['widgetName'] = $meta['widget_name'];
$result['widgetBase'] = $meta['widget_base'];
wp_send_json_success( $result );
}
else
}
wp_send_json_error( array(
'error' => 'Custom error message'
));
}
}
Also, make the necessary security checks with check_ajax_referer.

Somewhere in your code, a 0 is being printed. It's not in the function you gave, but that function is obviously getting called somewhere. You can confirm this by changing echo $result to die($result), although this doesn't fix the root problem, which is that somewhere you have a print statement that shouldn't be there.

You need to add:
die();
after echoing the results.

Related

Unexpected end of JSON input - Uncaught SyntaxError

everybody. I have an AJAX call which returns me an error mentioned in the title. I believe this is the line which causes error: var obj = jQuery.parseJSON(data); Maybe I wrongly constructed userData.
This is my jQuery:
var userData = 'email=' + email + '&password=' + password;
$.ajax({
type: 'POST',
url: './api/getInfo.php',
data: userData,
success: function(data){
var obj = jQuery.parseJSON(data);
$('#name').html(obj.firstName + ' ' + obj.lastName);
...
},
error: function(){
alert('ERROR');
}
});
And this is getInfo.php:
if($_SERVER['REQUEST_METHOD'] == 'POST')
{
$email = prepareInput($_POST['email']);
$password = prepareInput($_POST['password']);
$stmt = $connection->conn->prepare('SELECT firstName,lastName,... FROM tb_users WHERE email = ? AND password = ?');
$stmt->bind_param('ss',$email,$password);
$stmt->execute();
$result = $stmt->get_result();
$obj = $result->fetch_assoc();
echo json_encode($obj);
}
Can someone tell me if I'm doing something wrong?
UPDATE
function prepareInput($data)
{
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
Data passed from PHP is empty even if $obj contains values (I checked this by echoing them) so it must be the problem with echo json_encode($obj); statement.
SOLUTION
I finally found the answer - Link. It was encoding problem. If some strings are not UTF-8 json_encode() will return empty string so to deal with this you need to convert these strings to UTF-8.
Since you mention: the success function does not receive any data
It seems the server response is empty, because (a) the credentials are wrong or (b) there is an error in PHP and your code never reaches the echo line.
Add some error handling / confirmation in PHP and make sure that $obj has a value before you return it.
try {
// ... sql code
if ( $obj && is_array( $obj ) ) {
echo json_encode( $obj );
} else {
echo json_encode( array( 'error' => 'wrong username or password' ) );
}
} catch (Exception $ex) {
echo json_encode( array( 'error' => $ex->getMessage() ) );
}
Update; notes for debugging the SQL
To test the SQL:
As first line in the condition (method == POST) add echo json_encode(array('resp'=>'test')); exit; and run the Ajax code.
Your console.log() should now display the {resp:test} JSON object. This way you know that your ajax call actually reaches the part with the SQL. If you still do not get any output then something else is wrong in your code...
First use a hardcoded SQL: Just enter email/password in WHERE that you know will give you a result. Do not use ->bind_param() or $_POST data, just execute a plain SQL statement and see if AJAX returns a value.
If Ajax works now, then modify the hardcoded SQL to move the static email/password string into bind_param(). Still not using $_POST data now, but we check if the bind_param method works. Again check if Ajax is still working.
If still working, then use direkt $_POST data in the bind_param() call, like ->bind_param('ss', $_POST['email'], $_POST['password']) - if this is working, then you know that there's a problem with the prepareInput() function.
When testing each step, you should quickly find out, which part is not working.
You don't seem to check if your execute is a success before you use the result.
If I was you I will try to console.log(data) before use jsonParse. I think you will find some surprise.
Also, check your apache logs. Maybe PHP throw you some warnings in it.

return ajax string is 'empty' but cant pin it to 'empty', Why?

I have a problem with or after I delete files to clear the DataTable.
here is the .success bit of my ajax call
success: function(data) {
var data = $.trim(data);
alert(data);
if (data == "empty"){
alert("What follows is blank: " + data);
}
else{
alert("What follows is not blank: " + data);
}
}
Now from this I get the first alert saying the following.
Then I run the if (data == "empty") bit to see if data is 'empty'
but if continues on its way to the alert("What follows is not blank: " + data); alert andd I dont know why.
Why is this happening. How should I be testing this then?
PHP RETURN SNIP
// Fetch all records after edit
$json= fetchAll();
echo ( sizeof($json) > 0) ? json_encode($json) : json_encode( $json['empty'] = >'empty' );
The string contains the " symbol at the start and end, so check if the string is equal to '"empty"' instead.

Cannot get AJAX answer to GET

I'm trying to achieve the following:
when you click on H1, JQuery GETs info for certain key from the server and sends it back to user, where jquery is showing prompt with this info. PHP in server.php
$link = mysql_connect("mysql.hostinger.com.ua", "_my_login_", "_my_password_") or die("NOOO!");
mysql_select_db("u994953720_db");
$key;
if(isset($_GET['Key'])) {
$key = $_GET['Key'];
$selected = mysql_query("SELECT * FROM `Table` WHERE `Key`='".$key."'", $link);
$selected_row = mysql_fetch_array($selected);
if($selected_row!=null){
$response = array(
"result" => $selected_row['Value']
);
echo json_encode($response);
exit;
}else{
$response = array(
"result" => "Nope."
);
echo json_encode($response);
exit;
}
}
jQuery in the main page:
$('h1').on('click', function () {
$.ajax({
type: 'GET',
url: '/server/server.php',
data: {
'Key': 'Roman'
},
success: function(data) {
alert(data.result);
},
dataType: 'json'
});
});
But I don't have any effect. Could you guys show me how to fix my mistakes?
P.S.Working not working example
P.S.I am only starting learning PHP, so there can be some really stupid mistakes.
UPDATE: I've done everything like you guys said (I don't care about safety yet), but it still doesn't work. In the console there is the following message:
XHR finished loading: GET "http://site0.hol.es/server/server.php?Key=Roman".
When I include error method to ajax:
error: function(requestObject, error, errorThrown) {
alert("request objqect: " + requestObject + " . Error: " + error + " . Error thrown: " + errorThrown);
}
, there is an alert: parsing error, unexpected token <
UPDATE 1: I've understood, that my while page is being writed to json result, like here, but I don't have any other echo-s, how can it happen?
UPDATE: I've figured out, that PHP was sending the whole page what it was placed in, so, I simply removed that) But thank you for your comments about safety, I'll correct it
By looking at your site I can see that you are returning HTML + JSON. Try throwing an exit after your echo:
echo json_encode($response);
exit;
Also - you are not handling a no data state at all. You should be do something like:
if(isset($_GET['Key'])) {
// your valid request code
} else {
echo json_encode(array('result' => false, 'reason' => "You must send a Key"));
}
Furthermore you can debug you php code by hitting the endpoint directly and var_dumping/debugging the code that is run there. For starters, what is the output of $selected_row = mysql_fetch_array($selected); when you go to http://site0.hol.es/server/server.php?Key=Roman
Finally - just little warning, as others have mentioned. You are wide open to SQL injection attacks. Look into using PDO -
What PDO is:
http://php.net/manual/en/book.pdo.php
Why to use it:
http://code.tutsplus.com/tutorials/why-you-should-be-using-phps-pdo-for-database-access--net-12059
How to use it: http://wiki.hashphp.org/PDO_Tutorial_for_MySQL_Developers

Why the static message is not coming from ajax file if no data found in mysql database?

I have a very strange problem and couldn't figure it out. I am working with AJAX/PHP and fetching the data from mysql database on user interaction by ajax call. Everything is working very fine and no problem at all. But only one issue which is persisting is when the data is not found in mysql database, then a user-friendly message is not returned from the server ajax file - the one part works and other doesn't. Here is my code -
This is my first file where the form reside (full code is not there; only js code) -
<script type="text/javascript">
$(document).ready(function(){
$("#selcustomer").change(function(){
var customers_id = $(this).val();
if(customers_id > 0)
{
$.ajax({
beforeSend: startRequest,
url: "ajax/ajax.php",
cache: false,
data: "customers_id="+customers_id,
type: "POST",
dataType: "json",
success: function(data){
if(data != "No result found.")
{
$("#img_preloader").hide();
$("#error").html('');
// $("#txtfname").val(data.fname);
// $("#txtlname").val(data.lname);
for(var key in data)
{
document.getElementById("txt"+key).value = data[key];
}
}
else
{
$("#img_preloader").hide();
$("#error").html(data);
$("input").each(function(){
$(this).val('');
});
}
}
});
}
else
{
$("#error").html('');
$("input").each(function(){
$(this).val('');
});
}
});
});
function startRequest()
{
$("#img_preloader").show();
}
</script>
And this is my server-side ajax file (php file) which interacts with database -
<?php
include("../includes/db-config.php");
if(isset($_POST["customers_id"]))
{
$customers_id = $_POST["customers_id"];
$query = "SELECT * FROM `tb_customers` WHERE `customers_id` = '$customers_id'";
$rs = mysql_query($query);
if(mysql_num_rows($rs) > 0)
{
$row = mysql_fetch_array($rs);
$customers_first_name = $row['customers_first_name'];
$customers_last_name = $row['customers_last_name'];
$customers_email_id = $row['customers_email_id'];
$customers_phone_no = $row['customers_phone_no'];
$customers_address_line_1 = $row['customers_address_line_1'];
$customers_address_line_2 = $row['customers_address_line_2'];
$customers_country = $row['customers_country'];
$data = array('fname' => $customers_first_name, 'lname' => $customers_last_name, 'emailid' => $customers_email_id, 'phoneno' => $customers_phone_no, 'addressline1' => $customers_address_line_1, 'addressline2' => $customers_address_line_2, 'country' => $customers_country);
echo json_encode($data);
}
else
{
echo "No result found.";
}
}
?>
The if part is working fine but when no data is found in database the else part is not sending the data back to jQuery code. I checked in browser console and saw the else part is returning the response but the jquery code in success: part of $.ajax is not running - neither within if, nor in else and also not outside of if/else. I mean to say that a simple alert is not fired with data under success when no data is found in mysql database. But when i remove all the data in ajax/php file and say simply write 123 then alert comes with 123 but not when the actual code is there. Can you plz tell me what is the issue behind this strange problem?
Your datatype is set to JSON in your AJAX call, so the return value must be a valid JSON.
When you are encountering the else condition, you are returning something that is not JSON.
Try this -
else
{
echo json_encode("No result found.");
}
Or something more flexible-
else{
echo json_encode(Array("err"=>"No result found."));
}
EDIT-
...But when i remove all the data in ajax/php file and say simply write
123 then alert comes with 123...
That is because a 123 (number) is valid JSON. Instead of 123, try writing No result and an error would be thrown, because No result (a string) needs quotes(which is taken care when you use json_encode).

jqGrid after Delete error

Here is the example delete options I'm using using in a jqGrid. It works just fine and my serverside scripts are working perfectly. The records get deleted, but there is something that goes wrong after the response from the server is received.
// Del Options
{
mtype: "POST",
modal: true,
url: "/internal/backupmanagement/backupmanager/deleteMySQLDB",
reloadAfterSubmit: false,
onclickSubmit: function () {
var post = $("#grid_" + o.id).jqGrid("getGridParam", "postData");
var server = post.serverID;
$.openDialog("load", "Deleting old database entry. Please wait...");
var selrow = $("#grid_" + o.id).jqGrid("getGridParam", "selrow");
var row = $("#grid_" + o.id).jqGrid("getRowData", selrow);
console.log("about to return", row, server);
return {
id: row.recid,
database: row.database,
server: server
};
},
afterSubmit: function (response, postdata) {
response = eval("(" + response.responseText + ")");
console.log(response);
return [true, "success"];
},
afterComplete: function (response, postdata, formid) {
response = eval("(" + response.responseText + ")");
var selrow = $("#grid_" + o.id).jqGrid("getGridParam", "selrow");
$("#grid_" + o.id).jqGrid("delRowData", selrow);
if (response.error == 0) {
$.openDialog("info", "Successfully deleted " + postdata.database + ".");
} else {
$.openDialog("info", "And error occured - " + response.msg + ".");
}
}
}
I get the following error before the afterComplete event is fired in the grid :
Uncaught TypeError: Object [object Array] has no method 'split'
So it seems something is being returned as an object when it was expecting a string. I'm not sure if my response from the server is formatted correctly and I wasn't able to find any expected response in the documentation either.
* UPDATE *
Server-side code as requested. I've just included the controller function that interacts with the jqGrid, the rest is working and happening further on in the application.
function deleteMySQLDB()
{
if (IS_AJAX) {
if (($this->Application->deleteMySQLDBData(
$_POST["id"],
$_POST["database"],
$_POST["server"]
)) === false) {
echo json_encode(
array(
"error" => 1,
"msg" => "Failed Deleting record from database: "
.$this->Application->error
)
);
return false;
}
echo json_encode(
array(
"error" => 0,
"msg" => "success"
)
);
return true;
} else {
header("Location: /");
}
}
I hope this helps to see what I'm currently returning to the grid.
* UPDATE *
What I have done is changed the source in the jqGrid plugin to include a toString() on the value before preforming the split.
On line 331 of jquery.jqGrid.min.4.3.1 :
var A=[];A=H.split(",");
Changed to :
var A=[];A=H.toString().split(",");
It seemed like a harmless change in the grand scheme of things and avoids arrays to be attempted to get split. Thanks a lot for the help guys. You certainly pointed me in the right place to start looking, Oleg!
Let's suppose that the origin of the described error is the code of your afterComplete callback. I think that you are using it in a wrong way. I don't understand some parts of the code, the part (testing of response.error) should be moved in afterSubmit.
The main problem will be clear if you examine the lines of code where afterComplete callback will be called. It will be executed inside of setTimeout with 0.5 sec delay. At the time new data in the grid can be loaded (or could be loading). So it would be wrong to use methods like delRowData and the value of selrow could be changed now.
I would strictly recommend you additionally don't use eval function. Instead of the line
response = eval("(" + response.responseText + ")");
it will be correct to use
response = $.parseJSON(response.responseText);
The code of onclickSubmit callback could be improved if you would use the fact that this inside of the callback (like the most other callbacks o jqGrid) are initialized to DOM element of the grid. So to get selrow option of the grid you can use
var selrow = $(this).jqGrid("getGridParam", "selrow");
instead of
var selrow = $("#grid_" + o.id).jqGrid("getGridParam", "selrow");
Another fact is onclickSubmit will be called by jqGrid with two parameters: options and postdata. The parameter postdata is rowid if you use don't use multiselect: true. In case of usage of multiselect: true the value of postdata parameter of the callback can be comma separated list of rowids of the rows which will be deleted. So the usage of postdata is better as the usage of selrow.
I"m making a good guess since you didn't include your server side code.
On the server you can return something like:
return Json(new { success = false, showMessage = true, message = "Error - You can't have a negative value", title = "Error" });
Then on your client you can have something to display a message (in this example if there was an error)
afterComplete: function (response) {
var DialogVars = $.parseJSON(response.responseText); //parse the string that was returned in responseText into an object
if (!DialogVars.success || DialogVars.showMessage) {
showDialog($('#Dialog'), DialogVars.message, DialogVars.title);
}
} //afterComplete

Categories