2
\$\begingroup\$

I've been asked to keep track of how long a user has been connected to a site without interruption.

So far the solution I've come up with is to use ajax to poll the site every now and then to check how much time has elapsed since the last call.

Any suggestions for possible improvements would be appreciated.

P.S: Not sure why but text isn't displaying if no text is in the div or echoed.

The javascript

<script type="text/javascript">
<!--
// trigger the function
toto("UserConnected.php",'scriptoutput');

-->
</script>

<script type="text/javascript">
var page = "UserConnected.php";
var timer = ""; // Not sure how to avoid conflicts between timers

function toto(url,target)
 {
 //alert("working");
   document.getElementById(target).innerHTML = 'sending...';
   if (window.XMLHttpRequest) {
       req = new XMLHttpRequest();
       req.onreadystatechange = function() {ajaxDone(target);};
       //req.open("GET", url, true);
       //req.send(null);
           req.open("POST", page, true);
           req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); 
           req.send("data=<?php echo $user->id; ?>");
   // IE/Windows ActiveX version
   } else if (window.ActiveXObject) {
       req = new ActiveXObject("Microsoft.XMLHTTP");
       if (req) {
           req.onreadystatechange = function() {ajaxDone(target);};

           //req.open("GET", url, true);
           //req.send();
           req.open("POST", page, true);
           req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
           req.send("data=<?php echo $user->id; ?>");

       }
   }
           timer = setTimeout("toto(page,'scriptoutput')", 1 * 60  * 1000);
}

function ajaxDone(target) {
    // only if req is "loaded"
    if (req.readyState == 4) {
        // only if "OK"
        if (req.status == 200 || req.status == 304) {
            results = req.responseText;
            document.getElementById(target).innerHTML = results;
        } else {
            document.getElementById(target).innerHTML="ajax error:\n" +
            req.statusText;
        }
    }
}
</script>

The PHP code

if( isset( $_POST["data"] ) ){
    $id = (int) $_POST["data"];

    $sql ='INSERT INTO users_timeconnected ( profil_id, last_ajax_call ) VALUES ('. $id .', NOW() ) ON DUPLICATE KEY UPDATE id=id';

    $db->query( $sql );

    $sql ="
    select (
        (   
            unix_timestamp( now() )
            - unix_timestamp( (select last_ajax_call from users_timeconnected where profil_id =" . $id ." ) )
        ) / 60
    )";

    $db->query( $sql );

    $timeSinceLastCall = $db->fetch_one();

    $sql = 'select minutes_connected from users_timeconnected where profil_id =' . $id;

    $db->query( $sql );

    $minutesConnected = $db->fetch_one();

    echo "current time:" . date("d/m/y : H:i:s", time()).'<br/>';
    echo "id:" . $id .'<br/>';
    echo "time since last call:" .$timeSinceLastCall.'<br/>';
    echo "connected:" . $minutesConnected.'<br/>';
    echo "lower than or equal to 6:" . (int)($timeSinceLastCall <= 6);

    if( $timeSinceLastCall <= 6 ){
        $timeSinceLastCall = 0; // reset
        $sql ='UPDATE users_timeconnected SET minutes_connected = minutes_connected+5 WHERE profil_id='. $id ;
        $db->query( $sql );
        $sql ='UPDATE users_timeconnected SET last_ajax_call = NOW() WHERE profil_id='. $id;
        $db->query( $sql );
    }
}

The SQL table

CREATE TABLE IF NOT EXISTS `users_timeconnected` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `profile_id` int(10) unsigned NOT NULL default '0',
  `last_ajax_call` timestamp NULL default NULL,
  `minutes_connected` int(10) default '0',
  PRIMARY KEY  (`id`),
  UNIQUE KEY `profil_id` (`profile_id`)
);

The html for tests

<div id="scriptoutput">Output</div>
\$\endgroup\$
1
2
\$\begingroup\$

Structure of your Javascript is tightly coupled with your logic, decoupling will allow change without major changes.

a) Move you Ajax initialization [xmlHttp] to a usable function.

b) UnIntended display of UserId req.send("data=<?php echo $user->id; ?>"); as plain text inside your javaScript is security risk

c) Refactor your client script and least packit(dean edwards works ok) and compress it.

d) Using a comet based server is Best solution to this rather than polling the server at defined intervals. I would recommend you learn APE Project

another point! you can do it this way, when user navigates away from page ask them a few seconds to send ajax request. You have login time and now you have leaving time , calculate Hit rate yourself. Also using LocalStorage will be viable option too

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.