I'm trying to set up a cookie which would store the time when the user leaves a website, so in the next visit he can find a "There's new content" message (if any) - checked against his "last seen" stored time.
The things I'm stuck with are two : how do I send a cookie when he leaves the site ? And, then, how do I check that data when he comes back, compared to the last published content's time ?
This is the code I have by now :
<!-- I send the cookie -->
<?php
// How long should something be considered new for? (In seconds.)
// seconds * minutes * hours * days
// Default is 72 hours (3 days).
$stillnew = 60*60*24*3;
setcookie('CookiePublishing', time()-$stillnew, time()+60*60*24*30, '/');
?>
<!--I check the cookie and print -->
<?php
$entrydate = last_comment_time();
if ($_COOKIE['CookiePublishing'] < $entrydate) {
echo '<p>New Comment!</p>';
}
?>
As you see, I imagine a function called last_comment_time() that I have still to figure out, but my main concern would still be the moment in which the cookie is sent.
Many thanks for any input / alternative solution.
I don't think it matters when he leaves the site, but rather, what comments are on the page when it's loaded. For example:
12:00 comment1
12:05 comment2
==loaded at 12:10, sees comments 1-2==
12:15 comment3
==leaves site at 12:20==
==arrives again at 1:10==
In this case, he should be notified that there are new comments, since the last time he saw the page, there were only comments 1-2.
You may want to consider using PHP's built-in session handling and using $_SESSION.
Anyway, you may need to solve this problem by using two variables: one for the last access time and one for the current access time; when the page is loaded, set the last access time to the current one, then set the current one to the system's time. That way, you can determine content by the value of the last access.
For example:
<?php
// set cookies
session_start();
$_SESSION['lastAccess'] = $_SESSION['currAccess'];
$_SESSION['currAccess'] = time();
// send the cookies in the HTTP headers
session_write_close();
?>
...
<?php
$last_stillnew = last_comment_time() - 60*60*24*3;
if ($_SESSION['lastAccess'] < time()-$last_stillnew) {
print "<p>New comment!</p>";
}
?>
You have to use javascript.
One way to do this is to have the user's browser ping the server every five minutes or so. If the user doesn't ping the server for 6-7 minutes, he's gone.
edit: To give a bit more detail, what you need to do is send a blind ajax request to the server (so don't bother waiting on a response or anything). The script receiving the request should update the user's "last ping" field in your database or wherever. To find the last time they visited, it's "last ping" + time between pings.
This isn't really necessary if you just want to list new comments, as in that case you could simply record the time the user views the page, and display comments since then the next time the user visits (as FryGuy mentioned).
However the ping method does address your question of finding the amount of time since the user has last visited.
One obvious problem is if the user doesn't have javascript. To minimize the problems caused by this, update the "last ping" with PHP every time the user views the page.
Related
I'm currently trying to display all online users on my SITE'S userpage using the php session variables. To do this, whenever a user logs in or out, a column in a database gets set to "1" or "0".. However this doesn't entirely work since the database doesn't get updated when the user closes their browser (and therefor destroys the session). So is there another way of checking if a certain sessionid is set??
I also want to know how the twitter and facebook handle this ?
You almost have it. The way that the vast majority of sites deal with the issue is to have a table like you do, but they add a timestamp to it and update the timestamp when a new page is loaded.
When querying the table, you simply look for say the last five minutes of active users and they are the "live" users on the site.
Technically, you don't even need to keep the "logged in/out" value in that table. If they have been logged in within the lat five minutes, they are probably still about.
There is no guaranteed, sure-fire, totally bullet-proof way of checking if a user is there or not. You can do some tricky JS to ping on and off, you can add even more JS that will try to alert the db when the user navigates away from the page - but at the end of the day, you cannot do anything if a browser is closed unexpectedly, or if that user loses power, or network.
On top of that web browsing is by default stateless and doesn't maintain a connection to the user after the server has finished sending code. The best we can efficiently do is update a table when the user does something new and assume they will be around for a few minutes at least.
I haven't checked but Twitter and Facebook most likely have Javascript code which notifies the server when somebody closes the page, probably coupled with a periodic heartbeat and timeout.
Check the onunload event and XMLHTTPRequest to see how you can make a request to your PHP application notifying of an user leaving (a library like jQuery might help you do this much more easily).
Add a field "last_visit" to user's Table and update it every time when user visit your site
When user login to your site find "last_visit" time and current time,after that use this function
$time_period = floor(round(abs($current_time - $last_visit)/60,2));
if ($time_period <= 10)
$online_offline_status = 1;
else
$online_offline_status = 0;
}
and then print your final result
<?php if (
$online_offline_status == 0){ ?>
<span style="color:#FF0000;">Offline</span>
<?php } else if ($online_offline_status == 1) {?>
<span style="color:#669900;">Online</span>
<?php }?>
I ran into a little problem with my college project again :(
<input type="text" name="timrem" value="" />
This is a hidden field that I want the data from.
if(isset($_REQUEST['timrem']))
{
$tim=$_REQUEST['timrem'];
}
This is the code used to get the value from timrem.
The variable timrem is used to initialize a countdown sequence on the page(implemented using javascript)
<span id="countdown-1" style="float:right"><?php echo $tim;?>
The value of the hidden field is dynamically changed via java script counter implemented.
sremtime=(parseInt(minRemain*60)) + (parseInt(secsRemain));
document.frmTest.timrem.value=sremtime;
this works fine when the page is submitted, ie, the time doesn't restart from the next page. But when the page is refreshed, the timer is restarted to the value of the $tim when the timer first started.
Is it possible to somehow get the value of the hidden input on page refresh?
And also, please comment on the approach taken to preserve the time elapsed to the next page. This is a project on online examination.
If you need your variable to persist across refreshes, you cannot rely on information passed back from client to server. The only information you can rely on is the information passed with the very first request, and that obviously doesn't include your time. The best solution I can think of is to store your timestamp in a session variable on the server:
session_start();
if(empty($_SESSION['timrem'])) $_SESSION['timrem'] = time(); // set this if it is the first time this page is loaded
$tim = time() - $_SESSION['timrem']; // $tim is now the number of seconds since the page was first loaded in this session
You do not need to pass the time back and forth between client and server to keep track of it, although your javascript will probably need it.
A good idea might be storing a timestamp either in your PHP page or in a database (for multiple users), and use it to generate $tim. Passing data on refresh doesn't seem possible as there is no request triggered.
How about you store a "target time" (what ever time remaining is counting down to) in your url. you could even store it in epoch time:
myurl.com/stuff.html?target_time=1359553896
that way when the page is refreshed you still have it with you and you can calculate time remaining from that. if you don't want it in your url, you could probably hide it on the page somewhere with a display:none style.
how about something like this:
http://jsfiddle.net/QpZcV/1/
I am writing a usersystem and as a statistic available for all my users I want to be able to provide them with the amount of hours they've been active on my website.
my original idea as to how to do this was:
user loads a page, and a record for the user is stored in a SQL table called accessLog
*user loads another page, sql query runs to see when they last visited a page*
if the user visited a page within the past two minutes, update their user account and add the time spent online
*insert a new record into accessLog*
however this would mean adding a potential of 4 additional queries to every single page of my website, which seems slow. I was thinking, there has got to be a more efficient way of tracking user activity online that I'm clearly too stupid to see!
My way of doing this is simple:
When a user loads a page, their "last page load time" is updated in the database.
A cron script runs every minute. It looks for users whose "last page load time" was in the last minute.
Increment the "time spent on site" for each user found.
In this way, I can keep track of users accurately to the minute. Just divide by 60 to get the hours.
I would use ajax to get the clients to call the server ever minute or so. Just a to tell the server that the user is still watching that page.
The server would have a lastTimestamp and a totalTimeSpentOnSite in a database. The lastTimestamp would simply have the last time a ajax request or page load occurred.
Every time the ajax fires the server would calculate now - lastTimestamp and add that to the totalTimeSpentOnSite.
To make it even more accurate you could
add javascript listeners to onBlur() to record only the actual time spent with that window active and then send that time to the server instead of just telling the server that the user is still active.
My philosophy is this: don't be overly concerned with efficiency until it becomes a problem. Unless your site has really heavy traffic, you won't notice the four queries. This might be simpler, though:
Log every page load.
Every few hours, run a script through cron that calculates time
spent online for each user and updates a running total in the user
table.
Periodically clear out your access_log table.
Add it to your session management. When a user starts their session record their start time. When the user ends their session record their end time. Simple math from there will gather you the total amount of time they are spending per session on your site.
To answer Filip Haglund
yeah but you'll have to wait for the session to time out, and that time doesn't reflect the actual time the user spent on the last page before he/she closed it.
That's true but then again, all of the answers available so far work on the same basic premise:
Log the page load time.
Log when the user leaves
Update a database table
It just so happens that to log when the user leaves you need sessions. I don't know of any other way in PHP to keep track of user activities the way OP wants. Updating the database table is a technical matter. Do you wanna use a CRON job? Do you wanna use AJAX? Do you wanna do something else?
If you really wanted to know how much activity was actually occurring you could send off AJAX requests for certain JavaScript events. This will tie the time tracking to actual browser events. Of course this means your time tracking relies on JavaScript being enabled.
The "two minute" rule is a little unreliable - and you can get tied up trying to work out what "time spent" actually means.
In a previous project, we did the following.
On each page load, we checked if the user had a current session, and if not, created a GUID to identify the current session.
We wrote a log record to the database with the datetime, GUID, page URL, and user ID (if the user had logged in).
To calculate "time spent", we calculated the time difference between the first and last record for the session GUID, and added one minute to reflect the time spent on the last page.
This is not entirely accurate, but it can run realtime without the need for CRON for sites with moderate amounts of traffic.
first choose a duration beyond which a session is considered interrupted. (ex: 10 minutes)
log all page load with all ip in database
if time between 2 page load for one ip is more than duration don't add this time to the total time for this ip
if time between 2 page load for one ip is less than duration add this time to the total time for this ip
2 problem is :
- if user stay more than duration (10 minutes) in a page without refresh he's considered as disconnected.
- the last page duration is not saved
Piwik works like that
This is what i use and it checks updates the DB anytime the user loads any page.
The data is accurate, as it calculates if the user loads a page per minutes, if so, it adds the time difference to the DB.
$now= time();
$stmt = $db_con->prepare(" SELECT last_seen,time_online FROM user_online_log WHERE user_id=? limit ? ");
$stmt->execute(array( $user_id, 1));
$fetch= $stmt->fetch(PDO::FETCH_ASSOC);
$last_seen=$fetch['last_seen']; //integer value from db, saved from time() function
$last_seen_plus_one_min= $last_seen + 60;
if( $now < $last_seen_plus_one_min ){
$additional_time_online= $now - $last_seen; }
else{ $additional_time_online = 0; }
//update db
$stmt12 = $db_con->prepare(" update user_online_log set last_seen=?, time_online = time_online+? WHERE user_id=? limit 1 ");
$stmt12->execute(array($now, $additional_time_online, $user_id));
I have a demo website for an e-test where each student is allowed 15 minutes for the whole exam (which comprises 5 subjects, each with 10 questions). I want it that, immediately a student clicks START on the home page, a countdown timer should start and update itself automatically. Actually, that is easily done for a single page.
The problem is if the student clicks to go the next page, I want the timer to begin from where it stopped on the previous page and continue counting down.
I thought of using SESSIONS but then how do I get Javascript to set the SESSION variable in PHP? The idea was to use AJAX but I do not know how to go about it.
Can anyone help me on it, even if it requires something other than AJAX?
PS:
What I want displayed is the number of seconds left, not the current time.
Thanks.
You don't have to know where it stopped on the other page.
You just want to know when the users clicked start.
Just save that in a database or a file even.
And on every request calculate the time left on the SERVER.
Since the client can be easily manipulated.
With the time left calculated on the server you can make a countdown using javascript on every page.
I found i simple way to do it, with a small search. Here
PHP:
//when you start
$_SESSION['start_time'] = time();
Then on every page:
<script type="text/javascript">
var startTime = <?php echo $_SESSION['start_time']; ?>;
//calculate remaining time
</script>
You can use an algorithm like this:
When the "start" event occurs, store the start time in a database.
Periodically send AJAX requests to a backend script. If the time has expired, return a response that ends the test.
There is not a real "timer" in this case -- just a start time, and logic to check if 15 minutes have passed since that time. If you want to display a timer to the user, the math will be straightforward.
You could just put the pages in IFrames and the countdown timer on the main page.
Simple, you store the timestamp of when the student first started the test and output it to each page. Then it's a simple matter of substracting current time from that timestamp to get elapsed time.
However, depending on Javascript is a very bad way of ensuring that this timer gets started. A better method is to force the user to click on an actual link/button, WITHOUT involving Javascript. You record the timestamp on the server then that hit comes in, and after that everything's fine.
start.php:
Start Test - Page 1
page1.php:
<?php
if(!isset($_SESSION['test_start_timestamp')) {
$_SESSION['test_start_timestamp'] = time();
}
?>
<h3>Question #1</h3>
etc...
The important thing is to never reset the timestamp value in the session once it's been set. Otherwise the test taker can simply click around until they reach a page where the counter's reset, and they can get more time for the test.
Environment : PHP/MySQL/Jquery
I would like to refresh the page (ex: index.php) when new data stores in to the table (ex : new_entry_table) checking for every one minute. The same page will be opened in many machines(pc-browsers) at a time all should get refresh when new data arises.
using jquery and database check i tried the following:
setInterval(function(){
$.post("new_data_check.php", function(data) {
if(data > 0){
$("#container").fadeOut('fast').load(location.reload());
}
});
return false;
},60000);
new_data_check.php: : checks
for new data in the test_db where
newdata_field=0 ; : If any new
data arises echo "1"; And update the
newdata_field=1; to stop constantly
refreshing the page. : else echo
"0"; : Just for a trigger
So the above jquery code checks new_data_check.php every 1 min for the trigger , if any trigger arises it will refresh the container.But its getting refresh only one opened session other opened sessions(in other browser or other pc) not getting refreshed.
Suggest a better way to do this. Thanks.
Your new_data_check.php file will need to keep track of all the users that are independently viewing the page.
If not, this will happen:
User 1 and User 2 are both logged into the site.
User 1 does the check 5 seconds before User 1, there is new data.
User 1 completes his request. The server clears the new_data bit.
User 2's request arrives 5 second later. Hedoes his request, but at this point, User 1 has set the new_data field to 0. His data is stale, but User 1 has effectively co-opted him.
By the looks of it, you're not supplying it with any information that would identify the user - unless the server is determining that using the IP address. If that's the case, remember that it's likely everyone behind a small network is going to have the same external ip address. So it can't tell people at an office apart.
What you could do is generate some kind of unique hash for each session and pass that off to the browser. The javascript can then provide the php script that same token.
Another solution without any sort of special bit, would be to pass along a timestamp with the request. Essentially, the client says "my latest bit of data arrived at 9:21:53 PM" The server then checks and responds "My most recent data was created before that, so you're still good. " or "I've got something that was created or modified on 9:22:53PM, you should download it."
With that method, you don't need to worry about who's who. Instead, you need to have modification/creation times on the data you're checking for staleness. You also need to make sure that the clients clock is synchronized correctly - better yet, don't trust the clients date and time information. Maybe utilize your new_data_check.php to provide the script with a timestamp it can pass along on subsequent requests.