Unexpected JSON behavior - javascript

I'm building a WordPress plugin. The PHP script sends the JSON, javascript receives it. Time to time, the js receives an empty JSON, even when I'm sure it should receive data. If I put an empty echo (echo ' ';), it fixes my problem and the data received correctly.
The receiver:
jQuery.ajax({
url: url + "get_bookings.php",
method: "POST",
data: {
week: t,
year: e
}
}).done(function(w) {
w = JSON.parse(w);
fetchTableData(w)
})
The sender:
echo ' ';
.
. // Code here.
echo json_encode( $query );
I couldn't find why this happens. Sometimes it works fine without the empty echo.
Edit: thanks for the answers, the exit did not help.
I checked the network panel, and it was requesting get_bookings.php twice. I put a slash at the end of the URL, and works fine.
url: url + "get_bookings.php/",

First, remove this line:
echo ' ';
Id suggest debugging the PHP script first by testing the resulting value for $query:
print_r($query);
If the value intermittently results as an empty string, then make sure to test for this and return an empty JSON object instead when necessary.
if (empty($query)) {
$query = (Object)[];
}
echo json_encode($query);

Please remove the second parameter true in json_encode and also issue is header already sent error.
You don't need header for json encode in ajax return. just add json_encode and that's it.

Related

Error 500 When Updating MySql Database from WordPress - Same Code Works Fine Outside of WordPress

I need to update a MySql database from inside a JS function within a WordPress Woocommerce page. I'm using Ajax to do this. The following code works fine as a stand-alone code but when I put it into the WordPress page (on my localhost) it throws an error 500. Also I put the required data (which will eventually be a variable) onto the end of the url (?test=14230) because I couldn't get it to send the data when using the data: line in the Ajax.
Here's the Ajax:
function db()
{
$.ajax({
url: 'update_db.php?test=14230',
type: 'post',
data: 0,
success: function(output)
{
alert('Success, server says '+output);
}, error: function()
{
alert('Something went wrong.');
}
});
}
Here's the update_db.php:
<?php
if(isset($_GET['test']) ){
$id = $_GET['test'];
}
include 'database-handler.php';
$sql = "UPDATE db_name SET column = 'Some Value' WHERE id = $id";
if(mysqli_query($conn, $sql)){
//echo ('<p>'."Success.".'</p>');
} else {
//echo ('<p>'."Something went wrong. $sql. " . mysqli_error($conn).'</p>');
}
mysqli_close($conn);
?>
So I'm just wondering why this works as a stand-alone code but not when it's inside WordPress?
Edit: Here is the error log:
[Wed Nov 09 15:16:47.543162 2022] [php:error] [pid 4564:tid 1828] [client ::1:5888] PHP Fatal error: Uncaught TypeError: mysqli_query(): Argument #1 ($mysql) must be of type mysqli, null given in C:\xampp\htdocs\my-sites\wowcard\wp-content\themes\blocksy-child\woocommerce\single-product\save-card-size.php:17\nStack trace:\n#0 C:\xampp\htdocs\my-sites\wowcard\wp-content\themes\blocksy-child\woocommerce\single-product\save-card-size.php(17): mysqli_query(NULL, 'UPDATE new_card...')\n#1 {main}\n thrown in C:\xampp\htdocs\my-sites\wowcard\wp-content\themes\blocksy-child\woocommerce\single-product\save-card-size.php on line 17, referer: http://localhost/my-sites/wowcard/product/polka-dot-brush-strokes-two-photo-birthday-card-purple/?card=complete&id=14230
Edit:
I believe the issue I had was due to the Ajax being embedded within more than one WordPress function and also a Woocommerce action. The variable I needed was not being passed from my PHP to the Ajax like it normally would be. I used a session variable instead, which fixed that particular issue.
The Ajax now uses the "data:" line to pass the data over to save-card-size.php rather than passing it inside the url. I would show the code but the editor is too glitchy on this site, it wouldn't allow me to copy and paste my code properly.
I also had to replace the include in save-card-size.php with the contents of database-handler.php.
Everything is now working.
WordPress has its own database handler which is automatically loaded, there are most likely conflicts between your code and WordPress, but without seeing the actual error, I can not give more information.
Check this out https://developer.wordpress.org/reference/classes/wpdb/
Example:
global $wpdb;
$results = $wpdb->query($wpdb->prepare( 'UPDATE db_name SET column = 'Some Value' WHERE id = %d' , $id ));

Errors while parsing invalid JSON passed from PHP to AJAX

I'm trying to parse JSON sent by PHP.
JSON:
[{"id":"1","value":"1"},{"id":"4","value":"1"},{"id":"2","value":"1"},{"id":"3","value":"1"},{"id":"4","value":"1"}]
I'm trying to parse it to get the id and pass it to another JavaScript function and I'm continuously calling the PHP. When I tried $.ajax, $.get, $.getJSON and used JSON.parse and parseJSON, I get this error:
Uncaught SyntaxError: Unexpected token <
because the JSON looks like this:
id: id: id: html> 1id: 4id: 1id: 2id: 3id: 4id: id: id: >
I tried to fix it using JSON.stringify, which caused this error:
Cannot use 'in' operator to search for 'length' in
and now I'm stuck and have no idea how to fix this.
test.php:
<?php
$link = mysql_connect("localhost", "root", "password");
if (!$link) {
die('Could not connect: ' . mysql_error());
}
$db = mysql_select_db("example");
$sql = "select * from data";
$x = mysql_query($sql);
$emparray = array();
while ($row = mysql_fetch_assoc($x)) {
$emparray[] = $row;
}
echo json_encode($emparray);
mysql_close($link);
?>
heatmap.html:
<script>
$(window).ready(function(){
$.ajax({
url:'test.php',
data:"{'id':'1', 'value':'1'}",
contentType: "application/json; charset=utf-8",
datatype: 'json',
success: function (data){setInterval(function(){
/* if I use parseJSON(data), I get "Unexpedted token <"
error */
$.each(data, function (id, value){ // error occures here
liveHeatMap(id); //Never called
});
}, 10000)}});
});
</script>
I think the problem is that the JSON is invalid. I have tried so many things and looked at many other similar problems but I still cannot fix it.
Remove the contentType and dataType properties in your AJAX request, and use an object (rather than a string) for your data. In your success function, remove the setInterval and manually parse the JSON string returned using JSON.parse(data). This ensures you have the most control over the data to prevent jQuery from causing problems (and also makes it clearer). jQuery may be interfering with the data in the process and you want the complete raw data.
It looks like you're receiving HTML. Common causes:
Your AJAX URL is pointing to the incorrect place (and it may not seem obvious -- try ./test.php or using an absolute path).
Your PHP is not killed after echoing the JSON. Replace mysql_close($link) with die() as when the script ends, all database connections are automatically closed anyway.
If you're still having issues, run these commands and comment their output:
console.log(data);
console.log(typeof data);

Sending data to PHP page to make a spreadsheet out of it

For some reason, when I try to send JSON data to a PHP page (where it gets downloaded as a spreadsheet), it runs without error, but doesn't bring up the prompt to download the spreadsheet. The JSON has generated without problem (I have made the PHP page create the file on the server, before trying to make it download without creating it).
Here is the JavaScript code that sends the JSON data to the server:
function writeToSpreadsheet()
{
// get the json for #theTable
var tableJSON = tableToJSON("tr:not(#titleRow)");
//alert(tableJSON);
alert("Sending table data to be written to the spreadsheet...");
$.post('/ResearchProject/tableContent/exportTable.php', {'table': tableJSON}).done(
function(response) { alert(((response == '') ? response : (tableJSON.title + ' written to file!')));})
.fail(function (xhr, ajaxOptions, thrownError) { alert("ERROR:" + xhr.responseText+" - "+thrownError); });
}
and here is exportTable.php
<?php
function cleanData(&$str)
{
$str = preg_replace("/\t/", "\\t", $str); // escaping all of the tabs
$str = preg_replace("/\r?\n/", "\\n", $str); // escaping any and all cases of carriage return
// if there is a single double-quote in the string, we wrap the string in quotes, replace every single double-quote with double double-quotes, and
// end with a double-quote
if(strstr($str, '"')) $str = '"' . str_replace('"', '""', $str) . '"';
}
// the data is coming from a JSON object that is being sent here
if (isset($_POST['table']))
{
$tableJSON = $_POST['table']; # somehow, this is already a PHP array (exactly the one we need)!!
// get the name of the table from the $tableJSON
$tableName = $tableJSON['title'];
// get the title row from $tableJSON
$titleRow = $tableJSON['titleRow'];
// fix the titleRow
foreach ($titleRow as $heading)
{
$heading = trim(preg_replace('/\s+/', ' ', $heading));
}
// get the rows from $tableJSON
$rows = $tableJSON['rows'];
// form the filename from the tableName
$fileName = $tableName . '.xls';
// here, we download the file without even creating it
header("Content-Disposition: attachment; filename=\"$fileName\"");
header("Content-Type: application/vnd.ms-excel");
// we echo the titleRow first
array_walk($titleRow, 'cleanData');
echo implode(chr(9), $titleRow) . "\r\n";
?>
<script>console.log('Title row written to file.');</script>
<?php
// now we echo the data
foreach($rows as $row)
{
array_walk($row, 'cleanData');
echo implode(chr(9), $row) . "\r\n";
?>
<script>console.log('Data row written to file.');</script>
<?php
}
}
else
{
echo 'You sent me no data :(\n';
}
?>
OK, MikeWarren, how do I test this??
You can test it by selecting a table from the dropdown menu and clicking the "Export table to spreadsheet" button here: http://dinotator.biokdd.org/ResearchProject/tableViewer.php
I am trying to have it where the table that is on the HTML page gets converted into an JSON object, and then downloaded. Thus, I would need to POST the data to the PHP page, right? (Query strings don't work.)
Query strings won't work because you are using jQuery's $.post call which means that your data is sent in the body of the request, as opposed to a query string which is what a GET uses. For JSON you do indeed want to use a POST.
As for what's going wrong, you need to decode your JSON into a PHP array using json_decode. Unfortunately it can't simply handle JSON how it is.
So most likely you'll want to do:
// now a poorly named variable
$tableJSON = json_decode($_POST['table']);
Also, looking at your Ajax, $.post does accept a .fail() listener, but it doesn't pass any error data as part of the callback. So if you want to be able to handle incoming response errors you'll need to use $.ajax:
$.ajax({
type: "POST",
url: "/your/url.php",
dataType: "json",
error: errorCallback
});
Finally, looking at how your code is structured, if you're actually trying to save to file, you're going to need some more logic. Right now, you're just rendering that table, and then returning it as a response which will show up in your done function. You're going to add some more logic in order to make it actually download. This question entails your exact problem.
Good luck!
I have found so much bad advice on the internet about how to solve this problem. One of the answers here also didn't work. :(
I have decided to get advice from a friend of mine, and me and him have decided on this approach:
Have my exportData.php simply write the data to $_SESSION, echo a JSON-encoded "success", and then exit
On exit, on the client-side of things, if "success" has been received, have the JavaScript open up a new tab to a file that I have created called downloadFile.php which actually does the downloading.
Why didn't sending the data between files work?
Downloading data entails setting the right headers and printing the data. When you send data to the file to do this (via AJAX), the buffer that the data is printed to is the one for response. You can see this by saying something like
success: function(response)
{
alert(response);
} and see the data that you "downloaded" not get downloaded, but get printed on-screen.
However, if you go to the file instead of simply passing data to it, your data will download, provided that it has access to the data that you are trying to download. You can see examples of this here: www.the-art-of-web.com/php/dataexport/ . In those examples, the data was "static" (that is, only existing in the scope of that PHP file, until download happened).
We then see that we should let another file handle the downloading. Here is what its contents should look like:
<?php
if (!isset($_SESSION))
session_start();
function cleanData(&$str)
{
$str = preg_replace("/\t/", "\\t", $str); // escaping all of the tabs
$str = preg_replace("/\r?\n/", "\\n", $str); // escaping any and all cases of carriage return
// if there is a single double-quote in the string, we wrap the string in quotes, replace every single double-quote with double double-quotes, and
// end with a double-quote
if(strstr($str, '"')) $str = '"' . str_replace('"', '""', $str) . '"';
}
// get the data from $_SESSION
if (isset($_SESSION))
{
$fileName = $_SESSION['fileName'];
$titleRow = $_SESSION['titleRow'];
$rows = $_SESSION['rows'];
// set the excel headers
header("Content-Type: application/vnd.ms-excel");
//header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"$fileName\"");
header("Pragma: no-cache");
header("Expires: 0");
// attempt download
array_walk($titleRow, 'cleanData');
echo implode(chr(9), $titleRow) . "\r\n";
// now we echo the data
foreach($rows as $row)
{
array_walk($row, 'cleanData');
echo implode(chr(9), $row) . "\r\n";
}
}
else
{
die('Problem with session variable. Data could not be sent for download.');
}
exit;
?>
Of course, before doing this, make sure that you have 'fileName', 'titleRow', and 'rows' already written to $_SESSION.
This should help anyone having problem downloading HTML table to Excel spreadsheet via PHP, and the best part is that you don't have to bloat your server by downloading an entire library, for potentially the functionality of one button!!

Stringified data sent via Jquery post is unusable

I am stringifieng an object in javascript, and sending it via Jquery post method:
reservation={};
count=0;
$(".reservation").each(function() {
reservation[this.id]=jQuery(this).val();
count++;
if (count==jQuery(".reservation").length)
{
reservationString=JSON.stringify(reservation);
$.post("helper.php", {reservation: reservationString}) .done(function(data) {
The "helper.php" file gets the data, but the quotatian marks are all escaped, so when I try to decode it, I get a json error, with error code 4.
Here is the helper.php file:
$reservation=$_REQUEST['reservation'];
echo $reservation . "\n";
$reservation=json_decode(html_entity_decode($reservation));
I tried alerting out the reservationString in javascript, the string is not escaped there, so most likely the jQuery post method escapes the string for me. What could be the problem, can you guys suggest a solution?
Additional Infos:
This is what I get after alerting out the stringified object in javascript:
{"test":"bubub","Domain":"online","Type":"banner","s2id_CompanyId":"","CompanyId":"-","ContactPersonId":"0"}
This is what I get after echoing out the data in php:
{\"test\":\"bubub\",\"Domain\":\"online\",\"Type\":\"banner\",\"s2id_CompanyId\":\"\",\"CompanyId\":\"-\",\"ContactPersonId\":\"0\"}
This should work:
$reservation=$_REQUEST['reservation'];
echo $reservation . "\n";
$reservation=stripslashes(json_decode(html_entity_decode($reservation));

Why does jsonp return "Unexpected Token :" when using $.ajax() when my json is properly formated?

I'm using the below code to grab json from a remote address and use it's information in my project as a javascript object.
$.ajax({
type: "POST",
dataType: "JSONP",
url: "http://www.edupal.co/deals/?email=wed#umbc.edu",
jsonCallback: 'parseResponse',
success: function( data ){
console.log($.parseJSON(data));
},
error: function( xhr, str, e ){
console.log( "There was an error with the request", str, e );
},
complete: function(){
console.log("The request has completed.... finally.");
}
});
The problem is that although the request is being made just fine (I can see it in my networks tab in dev tools), it is telling me in my javascript console that there is an "Unexpected Token : "
Here is the JSON that is returning:
{"0":"1","id":"1","1":"20% Off UMBC Hoodies","title":"20% Off UMBC Hoodies","2":"umbc","school":"umbc","3":"UMBC Bookstore","location":"UMBC Bookstore","4":"http:\/\/bookstore.umbc.edu\/StoreImages\/9-862269-1.jpg","picture":"http:\/\/bookstore.umbc.edu\/StoreImages\/9-862269-1.jpg","5":"Limit 1 per person. Must present EduPal app with deal to cashier to be awarded discount.","description":"Limit 1 per person. Must present EduPal app with deal to cashier to be awarded discount.","6":"http:\/\/www.globatum.com","link":"http:\/\/www.globatum.com","7":"7\/30\/2014,08:45","start":"7\/30\/2014,08:45","8":"7\/30\/2014,09:45","end":"7\/30\/2014,09:45","9":"active","status":"active","10":"0","clicks":"0","11":"2014-07-30 20:18:30","posted":"2014-07-30 20:18:30"}
So i'm confused at what the problem could be. Can anyone help? I put it all in jsfiddle if anyone wants to test it. http://jsfiddle.net/#&togetherjs=T0ztQQbitP
Here is the PHP that generates the JSON
<?php
include('../dbconnect.php');
header('Content-Type: application/json');
$email = $_GET['email'];
$email = substr($email, 0, strpos($email, ".edu"));
$email = strstr($email, '#');
$school = str_replace('#', '', $email);
$sql = "SELECT * FROM `ads` WHERE `school` = '$school' ORDER BY `posted` DESC";
$result = mysql_query($sql);
$count = mysql_num_rows($result);
if($count > 0){
$deals = array();
$deals = mysql_fetch_array($result);
echo json_encode($deals) ;
}
else{
echo 'No records';
}
?>
It is not properly formatted.
JSONP must be a JavaScript program consisting of a single function call (to a function specified in the query string (usually via a callback parameter) which passes one argument (usually an object or array literal).
Your quoted response consists of a JavaScript object literal. Since the property names are identifiers instead of strings, it isn't even JSON. Since you are missing , between key:value pairs, it isn't even valid JavaScript.
The actual response I get (it looks like you are copy/pasting from the Chrome visualisation of the JSON instead of the source code) when I hit that URL is JSON — but not JSONP. So you shouldn't tell jQuery to process it as JSONP.
Since the URL doesn't appear to give permission via CORS, there doesn't appear to be any way to hit it directly with client side JavaScript unless you are hosting your HTML on www.edual.co so you'll need to use some server side code to relay the data to your JS.
JSON requires double-quotes around keys and commas for all but the last item.
...
clicks: "0"
...
should be...
...
"clicks": "0",
...
Note: even integer "keys" need to have double-quotes. So 0: "..." should be "0":"..."
Check out JSONLint in the future to double-check your JSON.
Also, JSON is not JSONP (source). You specify dataType: "JSONP", but you may just want dataType: "json". If so, as Barmar mentioned, you don't need to call $.parseJSON at all since data will already be a JSON object.

Categories

Resources