My long polling implementation isn't working. Been having a very difficult time understanding where to look toward debugging said code.
Key Points
No Errors
Long polling working randomly (only responds to some changes in MySQL with no distinct pattern)
MySQL is updating correctly
I'm testing this via Localhost WAMP and two browsers with two different sessions
PHP Portion -
$path= $_SERVER[ 'DOCUMENT_ROOT'];
$path .= "/config.php" ;
require_once($path);
require_once(PHP_PATH . "/classes/user.php");
session_start();
require_once(PHP_PATH . "/functions/database.php");
// Return to Login if no Session
if(!isset($_SESSION['user'])){
header("Location: /login");
die();
}
$db = connectdatabase();
$timeout = 40;
// if no post ids kill the script // Should never get here
if(!isset($_POST['post_ids'])){
die();
}
if(!isset($_POST['timestamp'])){
die();
}
$last_ajax_call = $_POST['timestamp'];
$post_ids = trim(strip_tags($_POST['post_ids']));
$id = $_SESSION['user']->getID();
// Check if there are posts from the last search that need to be updated with a comments or the like number has to be updated
$query = "SELECT posts.*, users.first_name, users.last_name, users.picture
FROM posts
LEFT JOIN users
ON users.id = posts.user_id
WHERE ((UNIX_TIMESTAMP(posts.date) > :last_ajax_call OR UNIX_TIMESTAMP(posts.last_modified) > :last_ajax_call)
AND posts.parent IN (:post_ids)) OR (posts.id IN (:post_ids) AND UNIX_TIMESTAMP(posts.last_modified) > :last_ajax_call)";
while ($timeout > 0) {
$check_for_updates = $db->prepare($query);
$check_for_updates->bindParam(':post_ids', $post_ids);
$check_for_updates->bindParam(':last_ajax_call', $last_ajax_call);
$check_for_updates->execute();
$r = $check_for_updates->fetchAll();
if(!empty($r)){
// Get current date time in mysql format
$unix_timestamp = time();
// Cofigure result array to pass back
$result = array(
'timestamp' => $unix_timestamp,
'updates' => $r
);
$json = json_encode($result);
echo $json;
return;
} else {
$timeout --;
usleep( 250000 );
clearstatcache();
}
}
// you only get here if no data found
$unix_timestamp = time();
// Cofigure result array to pass back
$result = array(
'timestamp' => $unix_timestamp
);
$json = json_encode($result);
echo $json;
JQuery Ajax -
function getUpdates(timestamp) {
var post_ids = $("#newsfeed").find("#post_ids").attr('data-post-ids');
var data = {'timestamp' : timestamp,
'post_ids' : post_ids};
poll = $.ajax({
type: 'POST',
url: '/php/check_for_updates.php',
data: data,
async: true, /* If set to non-async, browser shows page as "Loading.."*/
cache: false,
success: function(data) {
try {
// put result data into "obj"
var obj = jQuery.parseJSON(data);
// put the data_from_file into #response
//$('#response').html(obj.data_from_file);
// repeat
console.log("SQL: " + obj['timestamp']);
setTimeout( function() {
// call the function again, this time with the timestamp we just got from server.php
getUpdates(obj['timestamp']);
}, 1000 );
} catch( e ) {
// repeat
// Get mysql formated date
var unix_timestamp = Math.floor(Date.now() / 1000);
console.log("JS: " + unix_timestamp);
setTimeout( function() {
getUpdates(unix_timestamp);
}, 1000 );
}
}
}
);
}
Thanks for all the help guys! I asked around a lot of people and got a bunch of great places to look to debug the code.
I finally found the answer here -
http://blog.preinheimer.com/index.php?/archives/416-PHP-and-Async-requests-with-file-based-sessions.html
http://konrness.com/php5/how-to-prevent-blocking-php-requests/
It looks like I the PHP checking for updates was blocking any updates from happening till the PHP stop checking for updates.
Couple things you can do is:
1.) Open the Chrome Developer tools and then click on the Network tab and clear everything out. Then click on submit. Look at the network tab and see what is being posted and what isn't. Then adjust accordingly from there.
2.) Echo out different steps in your php script and do the same thing with the Network tab and then click on the "results" area and see what's being echoed out and if it's as expected.
From there, you should be able to debug what's happening and figure out where it's going wrong.
Related
I have a page that makes an Ajax call, which retrieves, JSON encodes and returns data from a database. The page was working, but in the midst of making some changes, it's now failing. (Should note that I'm working with a test site and test database as I make the changes.)
The errorThrown parameter of the error case shows me "SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data."
Here's the function with the Ajax call. (I've enhanced what's in the alerts for debugging purposes. I'll rip that back out once things are working.)
function acceptConfCode(){
var emailAddr = $('#email').val();
var confCode = $('#confcode').val();
var fnargs = "ConfirmCode|'" + emailAddr + "'," + confCode ;
$.ajax({
url: 'retrievedata.php',
type: "POST",
async: true,
data: {"functionname":"confirmcode","arguments":fnargs},
dataType: "JSON",
success: function (obj) {
if (!obj.error) {
$('#logininfo').hide();
$('#emailrow').hide();
$('#coderow').hide();
$('#reviewactions').show();
updateListOfActions(obj);
}
else {
success = false;
alert("The confirmation code you entered didn't match or has expired. Please try again. Type 1");
}
},
error: function(xhr, textStatus, errorThrown) {
success = false;
alert("The confirmation code you entered didn't match or has expired. Please try again. Type 2. textStatus = " + textStatus + "; errorThrown = " + errorThrown);
}
});
};
The retrievedata PHP page is mostly a CASE statement. The relevant case is this (again with added debugging code):
case 'confirmcode':
if ($argcount <2) {
$returnval = 'too few arguments';
}
else {
$returnval = confirmcode($argsarray[0], $argsarray[1]);
echo "Back from confirmcode\r\n";
var_dump($returnval);
}
break;
At the end of the page, it returns $returnval.
The key action is in the confirmcode function, which runs a MySQL SP to confirm that the user has a valid email and code, and then calls another function to retrieve the actual data. Here's confirmcode. As the commented out pieces show, I've checked results along the way and I am getting what I expect and it's getting JSON encoded; I've ran the encoded JSON back through JSON_decode() in testing to confirm it was decodable.
function confirmcode($spname, $params, $errorstring = 'Unable to send requested data') {
$conn = connect2db();
$query = "SELECT ".$spname."(".$params.") as result";
//echo $query."\r\n";
$result = mysqli_query($conn, $query);
$allresult = "unknown";
if (!$result) {
$errmessage = mysqli_error($conn);
$allresult = $errmessage;
$allresult = json_encode($allresult);
//echo $errmessage;
die( print_r( mysql_error(), true));
}
else {
//echo "In else case\r\n";
//retrieve list of action submissions
$resultobj = mysqli_fetch_object($result);
if ($resultobj->result == 1) {
//echo "In success subcase\r\n";
$allresult = getsubmissions($conn);
//echo "After getsubmissions\r\n";
//print_r($allresult);
}
else {
//echo "In failure subcase\r\n";
$result = array('error'=>true);
$allresult = $result;
}
//echo "Before JSON encode\r\n";
$finalresult = json_encode($allresult);
//echo "After JSON encode\r\n";
//echo json_last_error_msg()."\r\n";
//var_dump($finalresult);
$allresult = $finalresult;
return $allresult;
}
}
Finally, here's getsubmissions, again with some debugging code:
function getsubmissions($conn) {
echo "In getsubmissions\r\n";
$query = "CALL GetSubmissions()";
$submissions = mysqli_query($conn, $query);
if (!$submissions) {
echo "In failure case\r\n";
$errmessage = mysqli_error($conn);
$allresult = $errmessage;
$allresult = json_encode($allresult);
echo $errmessage;
die( print_r( mysql_error(), true));
}
else {
echo "In success case\r\n";
$rows = array();
while ($row = mysqli_fetch_assoc($submissions)) {
$rows[] = $row;
}
$allresult = $rows; //json_encode($rows);
}
//print_r( $allresult);
return $allresult;
}
What's really weird is I have another page in the site that retrieves almost exactly the same data through an Ajax call with no problem. The one that works contains a few additional fields, and doesn't contain two date fields that are in this result.
In addition, the live version of the site retrieves exactly the same data as here, except from the live database rather than the test database, and it works. While this version of the code has some additional things in it, the only differences in the relevant portions are the debugging items. (That is, I've made changes, but not in the part I'm showing here.) That leads me to think this may be an issue with the test data rather than with the code, but then why does the other page work in the test site?
UPDATE: To try to see whether this is a data problem, I cut the test data way down so that it's only returning a couple of records. I grabbed the generated JSON and ran it through JSONLint.COM and it says it's valid.
UPDATE 2: With the reduced data set, here's the string that's returned from retrievedata.php to the Ajax call:
[{"ActionSource":"https:\/\/www.voterheads.com\/","ActionSourceName":"Wall-of-us","Title":"Sign up to get notified about local meetings","Description":"Sign up at www.voterheads.com to get notified about local meetings. When we did, using the free option, this is what happened: a page popped up with a list of municipality meetings in the zip code we entered. We clicked on one of the meetings, and presto! -- instant access to the date, time, location, and agenda of the meeting. Pretty awesome.","StartDate":null,"EndDate":null,"UrgencyDesc":"Anytime","UrgencyColor":"#00FF00","UrgOrder":"5","DurationDesc":"Ongoing","DurOrder":"6","CostDesc":"Free","CostOrder":"1","Issues":"Advocacy","Types":"Learn","States":"ALL","iID":"20"},{"ActionSource":"https:\/\/actionnetwork.org\/forms\/ctrl-alt-right-delete-newsletter-2","ActionSourceName":"Ctrl Alt Right Delete","Title":"Sign up to learn what the \"alt-right\" is up to","Description":"Understand how the right operates online. Sign up for a weekly newsletter.","StartDate":null,"EndDate":null,"UrgencyDesc":"Anytime","UrgencyColor":"#00FF00","UrgOrder":"5","DurationDesc":"An hour or less","DurOrder":"2","CostDesc":"Free","CostOrder":"1","Issues":"Advocacy","Types":"Learn","States":"ALL","iID":"25"}]
As noted above, JSONLint.COM says it's valid JSON.
I've found a solution, though I'm just starting to understand why it works. On retrievedata.php, I uncommented:
echo $returnval;
just before the Return statement and it's working again. So I think the issue is that since retrievedata is a page, but not a function, the return statement didn't actually return anything. I needed code to actually return the JSON-encoded string.
I am implementing own custom function for historical extract in CSV format from MySQL database using jQuery-Ajax in WordPress environment. I have an HTML where user selects the start date and end date and clicks on a button and then the process works.
When the JSON response is in the range of 900kb to 1 MB, then extraction works. But when the response size increases beyond this then AJAX callback goes in error and returns nothing.
Below is the JavaScript file:
jQuery(document).ready(function(jQuery) {
jQuery('#extract_btn').click(function(){
var startdate = jQuery( '#from-date' ).val();
var enddate = jQuery( '#to-date' ).val();
var data1 = {
action: 'hist_extract',
fromdate: startdate,
todate: enddate
};
// since 2.8 ajaxurl is always defined in the admin header and points to admin-ajax.php
jQuery.ajax({
type:"post",
url:MyAjax1.ajaxurl,
data:data1,
success:function(response) {
if (response == '')
return;
alert('Got this from the server: ' + JSON.parse(response));
JSONToCSVConvertor(response, "Historic Price", true);
},
error:function(xhr, status, error){
alert('Error in response');
var err = JSON.parse(xhr.responseText);
alert(err.Message);
}
});
});
});
function JSONToCSVConvertor(JSONData, ReportTitle, ShowLabel) {
alert('Start of Json Convertor')
//If JSONData is not an object then JSON.parse will parse the JSON string in an Object
var arrData = typeof JSONData != 'object' ? JSON.parse(JSONData) : JSONData;
var CSV = '';
//Set Report title in first row or line
//CSV += ReportTitle + '\r\n\n';
//This condition will generate the Label/Header
if (ShowLabel) {
var row = "";
//This loop will extract the label from 1st index of on array
for (var index in arrData[0]) {
//Now convert each value to string and comma-seprated
row += index + ',';
}
row = row.slice(0, -1);
//append Label row with line break
CSV += row + '\r\n';
}
//1st loop is to extract each row
for (var i = 0; i < arrData.length; i++) {
var row = "";
//2nd loop will extract each column and convert it in string comma-seprated
for (var index in arrData[i]) {
row += '"' + arrData[i][index] + '",';
}
row.slice(0, row.length - 1);
//add a line break after each row
CSV += row + '\r\n';
}
if (CSV == '') {
alert("Invalid data");
return;
}
alert(CSV);
//Generate a file name
var fileName = "Edding_";
//this will remove the blank-spaces from the title and replace it with an underscore
fileName += ReportTitle.replace(/ /g, "_");
//this trick will generate a temp "a" tag
var link = document.createElement("a");
link.id="lnkDwnldLnk";
//this part will append the anchor tag and remove it after automatic click
document.body.appendChild(link);
var blob = new Blob([CSV]);
if (window.navigator.msSaveOrOpenBlob) // IE hack;
window.navigator.msSaveBlob(blob, fileName+".csv");
else
{
var a = window.document.createElement("a");
a.href = window.URL.createObjectURL(blob, {type: "text/plain"});
a.download = fileName+".csv";
document.body.appendChild(a);
a.click(); // IE: "Access is denied"
document.body.removeChild(a);
}
}
Below is the functions.php having custom hook:
//----------------------------------------------------------------------------------
//Below is the custom Javascript hook for Historic Extract
//----------------------------------------------------------------------------------
function price_history() {
$handle = 'hist_extract';
$list = 'enqueued';
if (wp_script_is( $handle, $list )) {
return;
}
else
{
// registering and enqueueing the Javascript/Jquery
wp_enqueue_script('jquery');
wp_register_script('hist_extract', get_template_directory_uri() . '/js/Historic_Price.js', array( 'jquery' ), NULL, false );
wp_enqueue_script('hist_extract');
wp_localize_script('hist_extract', 'MyAjax1', array(
// URL to wp-admin/admin-ajax.php to process the request
'ajaxurl' => admin_url('admin-ajax.php'),
// generate a nonce with a unique ID "myajax-post-comment-nonce"
// so that you can check it later when an AJAX request is sent
'security' => wp_create_nonce('my-special-string')
));
error_log('Js for Historic Price loaded successfully');
error_log(admin_url('admin-ajax.php'));
}
}
add_action('wp_enqueue_scripts', 'price_history');
//----------------------------------------------------------------------------------
// Custom function that handles the AJAX hook for Historic Extract
//----------------------------------------------------------------------------------
function historic_data_extract() {
error_log('Start of report data function on ajax callback');
// check_ajax_referer( 'my-special-string', 'security' );
$from_date = $_POST['fromdate'];
$to_date = $_POST['todate'];
$convert_from_date= date("Y-m-d", strtotime($from_date));
$convert_to_date = date("Y-m-d", strtotime($to_date));
error_log($from_date );
error_log($to_date);
error_log($convert_from_date);
error_log($convert_to_date);
//******************************************
//Custom Code for fetching data from server database
//********************************************
//header("Content-Type: application/json; charset=UTF-8");
define("dbhost", "localhost");
define("dbuser", "xxxxxxxxx");
define("dbpass", "xxxxxxxxx");
define("db", "xxxxxxxx");
$emparray = array();
$conn = mysqli_connect(dbhost, dbuser, dbpass, db);
// Change character set to utf8
mysqli_set_charset($conn,"utf8");
if ($conn )
{
$query = "SELECT PR_PRICE_HIST_TBL.PR_PRODUCT_ID,PR_PRICE_HIST_TBL.PR_URL_ID,PR_PRICE_HIST_TBL.PR_SHOP_NAME,PR_PRICE_HIST_TBL.PR_LAST_CHECKED,PR_PRICE_HIST_TBL.PR_CUST_PROD_CODE,PR_PRICE_HIST_TBL.PR_PRODUCT_NAME,PR_PRICE_HIST_TBL.PR_LAST_PRICE,PR_PRICE_HIST_TBL.PR_CONV_PRICE,PR_PRICE_HIST_TBL.PR_DOMAIN,PR_PRICE_HIST_TBL.PR_COUNTRY_CODE,PR_PRICE_HIST_TBL.PR_AVAILABLE,PR_PRICE_HIST_TBL.PR_AVAIL_DESCR,PR_PRICE_HIST_TBL.PR_PRICE_TIME,PR_PRICE_HIST_TBL.PR_FAULT_FLAG,PR_PRICE_HIST_TBL.PR_FAULT_TIME,PR_PRICE_HIST_TBL.PR_FAULT_MSG,TABLE_72.MIN_PRICE,TABLE_72.MAX_PRICE,TABLE_72.AVG_PRICE,TABLE_72.DEV_PRICE
FROM PR_PRICE_HIST_TBL
INNER JOIN TABLE_72 ON PR_PRICE_HIST_TBL.PR_URL_ID=TABLE_72.PR_URL_ID AND
PR_PRICE_HIST_TBL.PR_SHOP_NAME=TABLE_72.PR_SHOP_NAME AND
PR_PRICE_HIST_TBL.PR_PRODUCT_NAME=TABLE_72.PR_PRODUCT_NAME
AND PR_PRICE_HIST_TBL.PR_LAST_CHECKED BETWEEN '$convert_from_date' AND '$convert_to_date';";
error_log($query);
$result_select= mysqli_query($conn,$query);
error_log(mysqli_num_rows($result_select));
error_log(mysqli_error($conn));
while($row = mysqli_fetch_assoc($result_select))
{
error_log(json_encode($row));
$emparray[] = $row;
}
//error_log(json_encode($emparray));
echo json_encode($emparray);
die();
}
}
add_action('wp_ajax_hist_extract', 'historic_data_extract');
add_action('wp_ajax_nopriv_hist_extract', 'historic_data_extract');
From the code above, you can see, I have tried to implement many things by going over different forums. But I am stuck here. I am not able to understand where could be the potential problem. FYI..I am hosting this on GoDaddy Server. I tried below things:
Tried to make query execution faster by removing views from join. It seems, query is fetching results in around 15 seconds
Format of the data in JSON and tried async: false, but not working
Tried to modify values in init.php. But of no use.
pload_max_filesize = 64M
post_max_size = 64M
memory_limit = 400M
file_uploads = On
max_execution_time = 300
Tried to implement (error:function) for AJAX response. Where only the first alert('Error in response'); is throwing. But can not see the XHR response text.
Any help is appreciated. Please let me know if I miss something or want more information.
The best way to solve the issue is to have a good night's sleep.
Thanks for your clues.
Issue was: In xhr my ajax request was going in cancelled status.
Solution: I was missing preventdefault() in my function.
Now I can see MBs of JSON response. Thanks again for provided clues.
Currently preventdefault() has solved my issue. If you feel, anything else also needs to be taken care as a best practice in my code. Please do not hesitate to comment.
Thanks.
I'm using PHP in conjunction with AJAX for a lot of functions on my site. I've implemented a sort of rate limiting system on the client-side with Javascript. Basically, disabling a button for 1 sec after it's clicked.
Although this works fine for the more innocent cases, but I feel like I need something on the server-side of things to limit requests as well.
Basically, I want users to have a maximum amount of AJAX calls they can make per second. In fact, one per second seems reasonable.
One way would be somehow logging every request to my AJAX callback, and reading from that table before a new request is made. But this would immensely increase the work load on my server and database.
Are there any alternative methods of doing this?
PHP
function comment_upvote_callback() {
// Some sort of rate limit??
// $_POST data validation
// Add upvote to database
// Return success or error
}
add_action( 'wp_ajax_comment_upvote_callback', 'comment_upvote_callback' );
jQuery
var is_clicked = false;
if ( is_clicked == false ) {
$('#comments').on('click', '.comment-upvote', function(event) {
event.preventDefault();
// Button disabled as long as isClicked == true
isClicked = true;
// Data to be sent
var data = {
'action': 'comment_upvote_callback',
'security': nonce,
'comment_id': comment_id
};
// Send Data
jQuery.post(ajaxurl, data, function(response) {
// Callback
// Client-side rate limit
setTimeout( function() {
is_clicked = false;
}, 1000);
});
});
}
As already told above, you should be using rate limiting at server-side
I have written a code to implement the same. You can copy the code into a file and simply include in your server-side script at the top. It accepts maximum 3hits/5secs. You can change the rate according to your needs
session_start();
const cap = 3;
$stamp_init = date("Y-m-d H:i:s");
if( !isset( $_SESSION['FIRST_REQUEST_TIME'] ) ){
$_SESSION['FIRST_REQUEST_TIME'] = $stamp_init;
}
$first_request_time = $_SESSION['FIRST_REQUEST_TIME'];
$stamp_expire = date( "Y-m-d H:i:s", strtotime( $first_request_time )+( 5 ) );
if( !isset( $_SESSION['REQ_COUNT'] ) ){
$_SESSION['REQ_COUNT'] = 0;
}
$req_count = $_SESSION['REQ_COUNT'];
$req_count++;
if( $stamp_init > $stamp_expire ){//Expired
$req_count = 1;
$first_request_time = $stamp_init;
}
$_SESSION['REQ_COUNT'] = $req_count;
$_SESSION['FIRST_REQUEST_TIME'] = $first_request_time;
header('X-RateLimit-Limit: '.cap);
header('X-RateLimit-Remaining: ' . ( cap-$req_count ) );
if( $req_count > cap){//Too many requests
http_response_code( 429 );
exit();
}
So I've been banging my head against my desk for a few hours on this one and i'm not getting anywhere so help would really be appreciated.
The code below has two jquery event handlers which fire off an ajax request. The first one uses GET and the data it gets back from the server is JSON encoded - it works fine. The second one ( "button#addTx" ) returns causes Firebug to produce this error:
uncaught exception: [Exception...
"prompt aborted by user" nsresult:
"0x80040111 (NS_ERROR_NOT_AVAILABLE)"
location: "JS frame ::
resource://gre/components/nsPrompter.js
:: openTabPrompt :: line 468" data:
no]
Line 0
which is no help to at all. The server side script is printing raw html to the screen and the aim is that a jquery html replace will be used to update to the page which initiates the request. The data is POSTed correctly as the database updates but beyond that I have no clue. I have rewritten it to try a GET and still produce the same error :-(
Help would be amazing - thank you, Simon
$(document).ready(function(){
$("button.delete").click(function(){
var txid = this.id;
var amountID = "#amount" + txid;
var amount = $(amountID).html();
// <![CDATA[
var url = "delete.php?txid=" + txid + "&am=" + amount;
$.ajax({
type: "GET",
url: url,
success: function(msg){
txid = "ul#" + txid;
$(txid).hide();
var values = msg;
var e = "#" + values.category + "AmountLeft";
var a = values.amount;
$(e).html(a);
}
});
});
$("button#addTx").click(function(){
// <![CDATA[
var url = "addTran.php";
//var dataV = var data = "category=" + document.getElementById("category").value + "&what=" + document.getElementById("what").value + "&amount=" + document.getElementById("amount").value + "&date=" + document.getElementById("date").value;
$.ajax({
type: "POST",
url: "addTran.php",
//async: false,
data: "category=Groceries&what=Food&amount=2.33&date=2/3/2011",
success: function(msg){
$("transList").replaceWith(msg);
}
});
});
});
and here is the server side script
<?php
session_start();
include('functions.php');
//if the user has not logged in
if(!isLoggedIn())
{
header('Location: index.php');
die();
}
$category = $_POST['category'];
$what = $_POST['what'];
$amount = $_POST['amount'];
$date = $_POST['date'];
$category = mysql_real_escape_string($category);
$what = mysql_real_escape_string($what);
$amount = mysql_real_escape_string($amount);
$date = mysql_real_escape_string($date);
$date = convertDate($date);
//add trans to db
include('dbcon.php');
$query = "INSERT INTO transactions ( category, what, amount, date) VALUES ( '$category','$what','$amount','$date');";
mysql_query($query);
//grab the remaining amount from that budget
$query = "SELECT amount_left FROM cards WHERE category = '$category';";
$result = mysql_query($query);
$row = mysql_fetch_array($result, MYSQL_ASSOC);
$oldAmountLeft = $row["amount_left"];
//update the amount left
$amountLeft = $oldAmountLeft - $amount;
mysql_free_result($result);
//add new value to db
$query = "UPDATE cards SET amount_left = '$amountLeft' WHERE category = '$category';";
mysql_query($query);
//generate the list of remaining transactions, print to screen to send back to main page
$query = "SELECT txid, what, amount, date FROM transactions WHERE category = ('$category');";
$result = mysql_query($query);
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
$d = convertDateReverse($row["date"]);
$what = $row["what"];
$amount = $row["amount"];
$txid = $row["txid"];
?>
<li><ul class="trans" id="<? echo $txid; ?>"><li class="date"><? echo $d; ?></li><li class="what"><? echo $what; ?></li><li class="amount" id="amount<? echo $txid; ?>"><? echo $amount; ?></li><button class="delete" id="<? echo $txid; ?>">Delete</button><li></li></ul></li>
<?
}
mysql_free_result($result);
mysql_close();
header("Content-type: application/x-www-form-urlencoded"); //do I need this? I have a " header("Content-type: application/json"); " in the working one
?>
PROBLEM SOLVED: so in the html markup the form that holds the fields of data should have an
onsubmit="return false;"
in it!
Thanks for all the help guys, I have implemented all your suggestions and my code is now soooo much smaller and easier to manage!
Cheers
Simon
Thx for posting the solution. Similarly banged my head for a while trying to solve a similar problem with NS_ERROR_NOT_AVAILABLE without luck. Useful for for people using Django <--> Javascript to do XMLHttpRequests as well. On the Django side, there is an
error: [Errno 32] Broken pipe
...that corresponds with the NS_ERROR that appears in the firebug console for the JS failure.(googleBait) It's hard to know where to start tracing the problem - server side or client side.
Thx again.
So I decided to start using prototype and here's my first question. I'm trying to send out an ajax request to a php page which updates s single record. When I do this by hand (ie: typing the address + parameters it works fine but when I use this code from javascript:
var pars = 'trackname=' + track + '&tracktime=' + time;
new Ajax.Request('php/setSongTime.php', {
method: 'get',
parameters: pars,
onSuccess: function(transport){
var response = transport.responseText || "no response text";
alert("Success! \n\n" + response);
},
onFailure: function(){ alert('Something went wrong...') }
The onSuccess fires and displays the correct information from php, but the update is not made. What the php returns is the UPDATE string, so I'm checking the parameters and they look fine. Does anyone see a problem? Thanks...
Total javascript:
/*This file handles all the user-based computations*/
//variable declarations to be used throughout the session
var untimedSongArray = [];
function beginProcess(){
new Ajax.Request('php/getUntimed.php', {
method: 'get',
onSuccess: function(transport){
var response = transport.responseText || "no response text";
untimedSongArray = response.split("+");
alert(response);
getFlashMovie("trackTimer").timeThisTrack(untimedSongArray[0]);
//alert("Success! \n\n" + response);
//var html = response;
},
onFailure: function(){ alert('Something went wrong...') }
});
}
function getFlashMovie(movieName) {
var isIE = navigator.appName.indexOf("Microsoft") != -1;
return (isIE) ? window[movieName] : document[movieName]; }
function setSongTime(track, time){
alert("track " + track + " has a time of " + time);
//$.get("php/setSongTime.php", { trackname: track, tracktime: time } );
var pars = 'trackname=' + track + '&tracktime=' + time;
new Ajax.Request('php/setSongTime.php', {
method: 'get',
parameters: pars,
onSuccess: function(transport){
var response = transport.responseText || "no response text";
alert("Success! \n\n" + response);
},
onFailure: function(){ alert('Something went wrong...') }
});
}
Total php code:
<?php
//turn on error reporting
ini_set('display_errors', 'On');
error_reporting(E_ALL | E_STRICT);
//header('Content-Type: text/xml');
/////////////Main script
//pull variables
//need to do some error checking here
$trackname = ($_GET['trackname']);
$tracktime = ($_GET['tracktime']);
//remove leading track information
$trackname = str_replace('../music_directory/moe/moe2009-07-18/', '', $trackname);
$trackname = str_replace('.mp3', '', $trackname);
//echo $trackname;
//connect with database
$con = mysql_connect("localhost","root","");
if(!$con){
die('Could not connect: ' . mysql_error());
}
mysql_select_db("musicneverstopped", $con);
//end connecting to database
//////////////////////////////////////////
//update given song time
$sql = "UPDATE songs SET length = ".$tracktime." WHERE unique_song_id = ".$trackname;
echo $sql;
mysql_query("UPDATE songs SET length = '$tracktime' WHERE unique_song_id = '$trackname'");
//error check
//if(!$attempt){
//die(mysql_error());
//}
//////////////////////////////////////////
//close database connection
mysql_close($con);//close mysql connection
?>
Anyone see any failing errors?
Try echoing the exact same SQL you actually run in mysql_query (store it in $sql then pass that into the query, instead of writing out the query twice).
Then try running the query that gets echoed out in the response directly in the mysql command line on your server and see what happens.
Also, just to echo Max on the importance of escaping your SQL queries, I would add to the input sanitisation that you should use bind variables in your query, rather than just concatenating your user input with the rest of the SQL.
Something like this would ensure your variables are suitably escaped to avoid an SQL injection attack.
$sql = "UPDATE songs SET length = '%s' WHERE unique_song_id = '%s'";
$query = sprintf(
$sql,
mysql_real_escape_string($tracktime),
mysql_real_escape_string($trackname)
);
mysql_query($query);
Found it! Somehow I was getting an extra space before the finalized $trackname. ltrim fixed it right up. Thanks to everyone and thanks to those that mentioned security features. I'll definitely implement those. Dan