AJAX Request in CodeIgniter Application Failing After Inactivity - php

The application I am working on is built in CodeIgniter, and the content is always loaded via ajax into the main content div.
This works without fail normally, apart from after the user has been inactive for a short while.
We haven't completely narrowed down the inactivity time required for the request to fail, but it's around 40 minutes or more of inactivity.
I've tried logging details to the console in the error callback of the AJAX request, but nothing is logged.
I'm thinking that it's related to a session expiry but I can't be sure. I know when using CodeIgniter, there are two sessions which are created automatically (PHPSESSID, and ci_session) so my instinct is that it has something to do with these, or one of them, expiring?
When the request fails the headers, preview, response and cookies tab on chrome's developer tools show nothing.
If anyone has experienced this before, or has any ideas what may be causing the problem, I'd appreciate the input.
Edit:
Below is the AJAX request which is experiencing the above problem.
All links within my application use this loadPage function instead of a standard redirect.
function loadPage(href, type, clickElem, changeHash) {
if(ajax_loading == true) { return false; }
ajax_loading = true;
$('#recording_area').slideUp('slow');
if(typeof queue_countdown !== 'undefined') { clearInterval(queue_countdown); }
if(type == 'sidenav') {
$('#sidenav_accordion .accordion-heading a').removeClass('on');
$('#sidenav_accordion .accordion-inner a').removeClass('on');
$(clickElem).parents('.accordion-group').find('.accordion-heading a').addClass('on');
$(clickElem).addClass('on');
} else {
page_requested = href.replace(/^\/([^\/]*).*$/, '$1');
if(!page_requested) { page_requested = 'dashboard'; }
nav_elem = $('.sidenav a[href="/' + page_requested + '"]');
if(nav_elem.html() != null) {
nav_elem_group = nav_elem.parents().eq(2).children().first().find('a');
if(!nav_elem_group.hasClass('on')) {
if(!nav_elem.parents().eq(2).children().first().next().hasClass('in')) { nav_elem_group.click(); }
$('.sidenav .on').removeClass('on');
nav_elem.addClass('on');
nav_elem_group.addClass('on');
}
}
}
current_ajax_request = $.ajax({
type: 'GET',
url: href,
dataType: 'html',
cache: true,
beforeSend: function() {
},
success: function(data){
$('#map-canvas').remove();
$('.content_wrapper script').each(function(){
$(this).remove();
});
$('#gbox_Customers').remove();
if ($.browser.msie && parseInt($.browser.version, 10) === 7) {
$('.content_wrapper').hide().html(data).show();
$('#content_overlay').hide();
} else {
$('.content_wrapper').fadeOut().html(data).hide().fadeIn();
$('#content_overlay').fadeOut();
}
$('.queue_loading').hide();
console.log('success ended');
},
error: function(xhr,status,error) {
/*
* The below console logs do not fire when the problem is occuring.
*/
console.log('ERROR');
console.log('xhr: ' + xhr);
console.log('status: ' + status);
console.log('error: ' + error);
$('#map-canvas').remove();
$.get('inc.404.php', function(data) {
if($.browser.msie && parseInt($.browser.version, 10) === 7) {
$('.content_wrapper').hide().html(data).show();
} else {
$('.content_wrapper').fadeOut().html(data).hide().fadeIn();
}
});
if ($.browser.msie && parseInt($.browser.version, 10) === 7) {
$('#content_overlay').hide();
} else {
$('#content_overlay').fadeOut();
}
$('.queue_loading').hide();
},
complete: function(data) {
console.log(data);
ajax_loading = false;
set_tooltips();
}
});
if(changeHash != false) {
window.location.hash = "!" + href;
}
}
Edit 2:
After putting several console log's through the function, to see at which point it breaks. The problem decided to disappear. For what reason would adding console logs to the function prevent this issue from occurring?
I'm currently waiting an hour or so to re-test it without the console logs to make sure it isn't a red herring.
Edit 3:
After putting in console logs in the error callback of the AJAX request, it seems that the error callback is not firing. Not quite sure where to look now - as if it was a success, it would surely return the content.

Unsure what's causing your problem. But just in case this helps, here is a solution to a ajax and CI session problem I had.
Ajax requests would fail occasionally because the user would get logged out when the ajax request was made. (Not really sure why)
To fix the issue avoid a session update on ajax requests. To do this create a custom session class that overrides the sess_update method.
application/libraries/MY_Session.php
class MY_Session extends CI_Session
{
public function sess_update()
{
if (!IS_AJAX) {
parent::sess_update();
}
}
}
IS_AJAX is defined in application/config/constants.php
define('IS_AJAX', isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest');

Related

How do I make jQuery wait for an Ajax Call to finish before it returns

I have a weak server
When clients repeatedly request ajax service, the server stops working
Frequent demand ajax
My server is weakening
I want to make only one request. Upon completion he will be able to make another request
function checkItemd(item_id){
$("#checkBtn"+item_id).html("Processing..(Wait)").removeClass("btn-success").addClass("btn-primary");
alert("One tool checked at a time - Click OK");
var payload_string = $("#payload_form").serialize();
$.ajax({
type:"POST",
url:"ajax-item-check",
data:payload_string + "&itemId=" + item_id,
dataType:"json",
success:function(result){
if (result.result=="success"){
if (result.works=="success"){
var checkBtnMessage = result.response ? result.response : "'Sent to ' Email ";
$("#checkBtn"+item_id).html(checkBtnMessage).removeClass("btn-primary").addClass("btn-success");
}else{
$("#checkBtn"+item_id).html("Error").removeClass("btn-primary").addClass("btn-danger");
setTimeout('removeRow('+item_id+');',1000);
}
}else{
$("#checkBtn"+item_id).html("Not available to sellers").removeClass("btn-primary").addClass("btn-warning");
}
}
});
return false;
If you want to stop the user making multiple parallel requests, you can just set a flag which causes the function code not to be executable if the request is already in progress.
e.g. look at the requestInProgress flag in this example:
var requestInProgress = false;
function checkItemd(item_id) {
if (requestInProgress == true) return false;
$("#checkBtn"+item_id).html("Processing..(Wait)").removeClass("btn-success").addClass("btn-primary");
alert("One tool checked at a time - Click OK");
var payload_string = $("#payload_form").serialize();
requestInProgress = true;
$.ajax({
type:"POST",
url:"ajax-item-check",
data:payload_string + "&itemId=" + item_id,
dataType:"json",
success:function(result){
requestInProgress = false;
if (result.result=="success") {
if (result.works=="success") {
var checkBtnMessage = result.response ? result.response : "'Sent to ' Email ";
$("#checkBtn"+item_id).html(checkBtnMessage).removeClass("btn-primary").addClass("btn-success");
}else{
$("#checkBtn"+item_id).html("Error").removeClass("btn-primary").addClass("btn-danger");
setTimeout('removeRow('+item_id+');',1000);
}
}else{
$("#checkBtn"+item_id).html("Not available to sellers").removeClass("btn-primary").addClass("btn-warning");
}
}
});
}
N.B. you might want to add an "error" callback so you can set the flag false again in the event of any kind of unexpected problem with the request. Otherwise the user would have to refresh the page before they could make the request again.

Handle session timeout when loading data through ajax with jquery DataTables

My application is behind a sign in, so when loading the data through ajax, I need to verify the user still has an active session. If the user does not have an active session, I return back with echo json_encode(array('TIMEOUT')); which outputs ["TIMEOUT"]. How do I read that response and send the user back to the sign in page?
In previous versions of DataTables, I was able to do the following:
"fnServerData": function ( sSource, aoData, fnCallback, result ) {
$.getJSON( sSource, aoData, function (json) {
if(json == "TIMEOUT")
{
window.top.location.href = "/sign_out?action=to";
return;
}
fnCallback(json)
} );
Under DataTables 1.10, fnServerData has been replaced by ajax (see docs and ajax.data). How do I accomplish the same thing with the new DataTables version? I feel like I am close, but it just isn't working...possible because I am doing something wrong attempting to parse the response (I never hit inside the if statement).
"ajax": {
"url": "/account/location_load",
"data": function (myJson) {
if(myJson == "TIMEOUT")
{
window.top.location.href = "/sign_out?action=to";
return;
}
return myJson;
}
}
After a day and a half working on it, I finally found a working solution using ajax.dataSrc (doc)
"ajax": {
"url": "/account/location_load",
"dataSrc": function (myJson) {
if(myJson == "TIMEOUT")
{
window.top.location.href = "/sign_out?action=to";
return "";
}
return myJson.data;
}
I don't know why this version allowed me to read myJson and the other didn't, but it works. The working PHP code ended up being echo json_encode('TIMEOUT');

Call PHP file in JavaScript Function for Updating MYSQL Table?

I want to integrate a Java script Slot Machine game into my script.
You can see demo here ; http://odhyan.com/slot/
And also git hub is here ; https://github.com/odhyan/slot you can see all JS files here.
I created a Point Coloumn in User Table that people can play the game with this Point.
I think this JS Function in slot.js checking if user won the game or lose.
function printResult() {
var res;
if(win[a.pos] === win[b.pos] && win[a.pos] === win[c.pos]) {
res = "You Win!";
} else {
res = "You Lose";
}
$('#result').html(res);
}
So i want to add +100 Point if user won the bet.
I made this PHP codes Uptading points For userid "1".
<?php
mysql_connect ("localhost","username","password") or die (mysql_error());
mysql_select_db('slot_machine');
$pointsql = mysql_query("SELECT * FROM user WHERE userid = 1");
while ($row = mysql_fetch_array($pointsql))
{
$row['point'] +=100;
$addpoint = mysql_query("UPDATE user SET point = '{$row['point']}' WHERE userid = 1");
}
?>
So how can i call or excute this PHP Codes in JavaScript function if user Win?
You'll need to trigger a network request from your javascript code to execute your php script server side. Using jQuery's $.ajax() function is an extremely common way to do this abstracting away various browser differences.
function printResult() {
var res;
if(win[a.pos] === win[b.pos] && win[a.pos] === win[c.pos]) {
res = "You Win!";
// Assign handlers immediately after making the request,
// and remember the jqxhr object for this request
var jqxhr = $.ajax( "path/to/your.php" )
.done(function() { alert("success"); })
.fail(function() { alert("error"); })
.always(function() { alert("complete"); });
} else {
res = "You Lose";
}
$('#result').html(res);
}
You can use jQuery's $.post() function to trigger an asynchronous request to your PHP file.
function printResult() {
var res;
if(win[a.pos] === win[b.pos] && win[a.pos] === win[c.pos]) {
res = "You Win!";
// Here's the line you need.
$.post('score.php', {userid: 1}, function(data) {
alert("Score saved.");
});
} else {
res = "You Lose";
}
$('#result').html(res);
}
This will send POST data to score.php, or whichever file you want to send the data to. The PHP file can then access the userid sent to it by checking the value of $_POST['userid'].
As mentioned in the documentation, $.post() is a shortcut for jQuery's $.ajax() function that is simplified and has some of its options pre-set. The third argument in $.post() is a callback function, and the variable data will contain whatever is echoed out or printed from score.php by the time it's done executing. So, you could use alert(data) instead, to see what score.php printed out. This is useful for troubleshooting and error handling.
try this
$(document).ready(function(){
setInterval(function() {
$.get("databaseUpdated.php");//or what ever your php file name is with corrct path
return false;
}, 1000);
});
hope this will help you use it in your function
function printResult() {
var res;
if(win[a.pos] === win[b.pos] && win[a.pos] === win[c.pos]) {
// if
setInterval(function() {
$.get("databaseUpdated.php");//or what ever your php file name is with corrct path
return false;
}, 1000);
} else {
res = "You Lose";
}
$('#result').html(res);
}

jQuery ajax success conditional..?

I'm running the following php script through AJAX and need to integrate some error management into it:
$exists = file_exists('../temp/' . $email . '/index.html');
if($exists) {
echo "ERROR!!!";
} else {
createUserDirectory($email);
}
In the AJAX success function, how can I determine whether the script ran successfully or produced an error?
If it returns OK, I want to perform the redirect as it is at the moment, but if there's an error, I want to instead add the error to a DIV within the document (and not redirect of course...).
$.ajax({
type: "POST",
url: 'generate/build.php',
data: $("#generateStart").serialize(), // serializes the form's elements.
success: function(data)
{
window.location.href="generate-site.php?user=" + data.replace(/^ +/,"") + ""; // Redirect to publish.php and remove any spaces from the URL (bug fix).
}
});
Thanks.
Your PHP script should return a 4xx or 5xx HTTP status code to indicate failure. Then, the error method of jQuery's ajax object will be called.
Inside your success handler, check if(data == 'ERROR!!!').
You probably want to add two parts to this: an error callback on the $.ajax function to see if the request failed on the net and then a check on the return value to see if it failed server validation (if a file exists in this case).
Example:
$.ajax({
...
success : function(data) {
if(data && data != "ERROR!!!") {
//redirect
}
},
error: function(jqXHR, textStatus, errorThrown) {
//Log error, display feedback to user, etc...
}
);

How to alert or warn a user that session will be expiring soon in php codeigniter

Basically I'm looking for a solution where a user is notified five minutes before the session expires.
The ideal solution will be count down notification that will have an option to renew the session.
If the countdown timer expires without the user refreshing the page, I need to log them out.
Since the session will be refreshed as soon as you go back server-side and the script calls session_start() you really need to do this in Javascript. However if the user has two browser windows open with a split session and one is inactive, while the user is still generating traffic with the other, then the javascript in the idle window would incorrectly report that the session was about to expire. So you'd need to implement your own ajax wrapper to detect the age of the session without calling session_start().
Something like:
$session_id=$_REQUEST[session_name()];
// if you use the default handler:
$session_last_access=filemtime(session_save_path() . '/' . $session_id);
$time_left=time() + session_cache_expire() - $session_last_access;
C.
Depends on what exactly you want to achieve. When someone uses multiple tabs/windows, a window can stay open for very long without the session expiring. AJAX operations complicate things even further. If you want accurate notifications, you will have to set up a timer, and when it fires, check via an AJAX request (taking care not to renew the session) whether the estimate is still accurate.
Added this script in view:
`
if(isSessionAlive >0)
{
var timer = {
time: 0,
now: function(){ return (new Date()).getTime(); },
start: function(){ this.time = this.now(); },
since: function(){ return this.now()-this.time; }
}
var timerId;
sess_expiration = <?=($this->config->config["sess_expiration"]*1000)?>;
alertTime = <?=($this->config->config["sess_time_to_alert"])?>;
timerId = window.setTimeout("pingCI()",sess_expiration-((alertTime*1000)));
jsBaseurl = "<?=($this->config->config["base_url"])?>";
}
function resetTimer(resetTime)
{
//alert('RESET Time'+resetTime);
window.clearTimeout(timerId);
timerId = window.setTimeout("pingCI()", resetTime);
return;
}
function pingCI()
{
if(isSessionAlive > 0)
{
$.ajax({
type: "POST",
url: "<?= site_url('users/getSessionTimeLeft') ?>/",
data: "sessid=<?=$this->session->userdata("session_id")?>",
success: function(transport)
{
response = transport;
if(response=='')
{
parent.location.assign(jsBaseurl+'users/logout');
}
else if((response<=(alertTime*1000)) || (response-1000<=(alertTime*1000)))
{
alertSessionTimeOut(response);
}
else
{
resetTime = eval((response - alertTime)*1000);
resetTimer(resetTime);
}
}
});
}
}
function alertSessionTimeOut(alertTimeExp)
{
if(isSessionAlive>0)
{
var response='';
var timerIdEnd;
timerAlert = window.setTimeout("forceLogout()",alertTimeExp*1000);
timer.start(); // start counting my friend...
fConfirm = confirm('Your Session is about to time out. Please click OK to continue the session');
if(timer.since() >= (alertTime*1000))
{
parent.location.assign(jsBaseurl+'users/logout');
}
if(fConfirm ==true)
{
$.ajax({
type: "POST",
url: "<?= site_url('users/keepAlive') ?>/",
data: "sessid=<?=$this->session->userdata("session_id")?>",
success: function(transport)
{
response = transport;
if(response=='')
{
parent.location.assign(jsBaseurl+'users/logout');
}
window.clearTimeout(timerAlert);
resetTimer(sess_expiration-((alertTime)*1000));
}
});
}
else
{
//parent.location.assign(jsBaseurl+'users/logout');
window.clearTimeout(timerAlert);
window.clearTimeout(timerId);
}
}
}
function forceLogout()
{
parent.location.assign(jsBaseurl+'users/logout');
}
And in Users Controller:
function getSessionTimeLeft()
{
$ci = & get_instance();
$SessTimeLeft = 0;
$SessExpTime = $ci->config->config["sess_expiration"];
$CurrTime = time();
$lastActivity = $this->session->userdata['last_activity'];
$SessTimeLeft = ($SessExpTime - ($CurrTime - $lastActivity))*1000;
print $SessTimeLeft;
}
function keepAlive()
{
$this->load->library('session');
$this->session->set_userdata(array('last_activity'=>time()));
if(isset($this->session->userdata["user_id"])) print 'ALIVE';
else print '';
}
`
One way is to store in one javascript variable the time remaining, and update the variable in every page refresh
Create one javascript function with one settimeout that verifies the value of the variable that you set in 1.)
Regards,
Pedro

Categories