How to detect when a user is not online? - php

Well I've a admin dashboard which is PHP-Coded.
Now I want to know about my ONLINE users. For which I created a table in data base called "ONLINE". When a visitor/user comes to my site its IP is save on my database & on dashboard, show me 1 user online.
The problem starts from here. I want that when a visitor/user leave my site (close the site, close the tab, and whole browser). This saved IP (in ONLINE table) of the user, migrate or transfer to another table in data base named "VISITORS".

Detecting a user exit is a bit fuzzy. You can use javascript to send an exit notification to your server such as:
window.onbeforeunload = function() {
... insert your ajax code here ...
}
There are a lot of conditions where that won't fire though, so a better way is to use check-in code. You can make a php script that inserts/updates the ONLINE table(assumes the IP field on your table is set to be a UNIQUE or PRIMARY key, also requires you to create a TIMESTAMP field on the table - I named it last_check_in):
<?php
... connect to database ...
$statement = $db->prepare("INSERT INTO `ONLINE` SET `IP` = ?, `last_check_in` = NOW() ON DUPLICATE KEY UPDATE `last_check_in` = NOW()");
$statement->execute([$_SERVER['REMOTE_ADDR']]);
Then you can put an ajax call on a timer(here's jquery's ajax page: http://api.jquery.com/jquery.ajax/ and you can use setTimeout in your callback to schedule the next update) to make the page check in.
Then you can change your query that shows online users to only show users who have checked in recently:
<YOUR QUERY> WHERE <your WHERE stuff> AND `last_checkin` > NOW() - INTERVAL 1 MINUTE
This would actually allow you to just use one table instead of two, but if you're set on using two tables, you can write another script that moves users who haven't checked in over and put that on a cron timer.

So, to "figure out if a user left" you need to store some kind of last-activity-timestamp and determine a threshold time period for what you consider "active". This could be 30 minutes, or 15, or an hour; it's really up to you.
You can accomplish two goals with one task by using MySQL to handle your sessions. Whenever you create or update a session, you can also store the IP Address and the timestamp when the session is being updated. If the user logs out, session_destroy() will be called, which will call destroy() in your session handler, where you can "move" the IP to the table for non-logged-in users. Using a custom session handler gives you a straightforward place to put all of the logic.

Use one table "VISITORS".
For Example, period is 1 hour.
Add field:
FirstActivityInHour (DateTime, TimeStamp or Int (minutes part))
LastActivityInHour (DateTime, TimeStamp or Int (minutes part))
If visitors leave site - you can not track this action, no action. You can track last action.
If LastActivityInHour near now moment - visitor online. Non-optimal query example (FirstActivityInHour, LastActivityInHour - DateTime):
SELECT ...
FROM "Visitors"
WHERE
LastActivityInHour > DATE_SUB(NOW(), INTERVAL 10 MINUTE)
AND
DATE_ADD(FirstActivityInHour, INTERVAL 1 HOUR) > NOW();

Related

Update sql post on specific date "behind the scenes"?

I have a php website with a news section and the posts are stored in an SQL database. Each post has an expiration date (i.e. 2016-03-01) and an active column that is set to true or false. Active = true shows post.
I want the active column to change from true to false on the expiration date so that the post is no longer visible on the page. I know how to do this with basic php but that requires an input from the website, i.e. a push of a button or the page to be loaded, for it to update.
Is there a way for the database (or php) to do this behind the scenes and update the post on that specific date?
I suppose you are using MySQL server. If this is the case, you can use events. You can define events to execute queries every hour, minute, etc.
CREATE EVENT remove_expired_posts
ON SCHEDULE
EVERY 1 DAY
DO
UPDATE posts SET active = 0 WHERE expiration_date <= NOW();
More generally though, you can avoid this and add an additional condition when selecting the posts to be shown:
SELECT * FROM posts WHERE active = 1 AND expiration_date > NOW();
The tip from #YUNOWORK worked fine. My web hotel didn't have crontab installed but I am now testing a web service that does the same thing. Works really great!
I'm using www.cronless.com right now. It's free and does what I want.

requesting unique id every page load

I'm creating a page that needs to select a Unique ID for every page load. It's basically a purchase order system, but the PO will be just the UID, so it's important that no user can get the same ID. I tried doing just calling upon last ID, then adding 1 and submitting, but that could create conflict if two or more users are entering at the same time. What's the best way to pull a UID for each page load? Any solutions?
Thanks
Lloyd
UniqId() is one way, but results in large numbers. As V Patel says, there's also "Auto Increment" and this is probably the option you want.
In MySQL set up a table (say "PurchaseOrders") with a field "po_id" and set that to be the primary key and auto increment. Add another field "po_status" (TinyInt*1) and another "po_lastused" (Date*1). Status will be 0=draft, 1=final, 2=shipped etc. LastUsed is the last time the user accessed the details.
When you want to create a new purchase order, INSERT INTO PurchaseOrders(po_status, po_lastused) VALUES(0, NOW()); Note: you've not specified the actual purchase order
You can get the po_id through asking for the "last insert id" (http://php.net/manual/en/mysqli.insert-id.php, http://php.net/manual/en/function.mysql-insert-id.php, http://www.php.net/manual/en/pdo.lastinsertid.php, depending on your coding library)
Store the po_id in a session variable so that when the user returns, you know their po_id(*2)
Each time a user access a purchase order, if "last updated" was more then 5 minutes ago, update the timer.
Periodically deleted all purchase orders that are draft and where last updated is older than your session (e.g. after a day)
This way, you'll end up with nice purchase order numbers that are easily quotable.
*1 For the purists, You can also use Enum for the status, and int for dates - depends on your preference. You can also set the date to be automatically updated. But I'm keeping it simple.)
*2 Again, for the purists, there is more security you could implement here to ensure the "other" users can't access someone else's purchase order, but this is enough to start.
You can use the uniqid function to get a unique key. Run it through hexdec if you need an integer.
PHP has one:
http://php.net/manual/en/function.uniqid.php
Use auto increment feature of the database in use, especially if you like it to be a number and don't need it till you want to persist it.

set status on record automatically after certain datetime

I have a form that users fill in to post their job advertisements and one of the fields they enter is the number of days to keep job 'open'.
I want to be able to automatically change the status of the job to 'closed' after the days that they have entered have elapsed.
The job table is already set up with status and expiry, I just need to know how to automatically change the status from 'open' to 'closed'.
I have little knowledge of MySQL and the queries that I would need to run.
Suggest that you don't keep status as a field in the database, but rather derive that status from the expiry date in your business or presentation tier. This could be done in your SQL code or in client code(PHP).
Some pseudocode:
INSERT INTO JobAd (Description, ExpiryDate)
VALUES (#Description, #Today + DaysToLive)
...
SELECT *
, CASE WHEN ExpiryDate<#today
THEN 'Expired'
ELSE 'Good to go'
END AS JobStatus
FROM JobAd ORDER BY JobStatus, ExpiryDate
When you pull those jobs out, use PHP to write the status back to the user, based partially on ExpiryDate. Again, this could be done in SQL or PHP.
Having the status derived means you won't have to create a maintenance process/task to go update an attribute in the database.

"viewed" system - once per user

I need to implement "viewed" system.
How it can be done, so that pressing F5 would not increase viewed number for more than 1 per user?
SO also has such system.
Cookies, sessions, db? How it is usually done?
You will need a combination of technologies here. Each user needs to be identified uniquely (using sessions, cookies, whatever works best in your scenario). From there, you will need to be maintaining a database of hits for an item with the user's unique key (stored in their cookie or session or whatever).
When the user accesses the page, check the database to see if that user's unique key already has a hit on that page. If not, add it. Regardless, once done, pull the total number of hits that the item has had from the database. Tahdah.
Just store in your database user_id, resource_id (eventually timestamp) and before you increase viewed value check whether SQL like this:
SELECT COUNT(*) FROM ... WHERE user_id = ? AND resource_id = ? (AND timestamp > NOW() - 7 DAYS or sth)
doesn't return 1.
This depends a lot on the situation. For example, if each user is logged in with a user ID, it would be very different then if you are doing a splash page where users are not expected to be logged in.
I will assume you are in the latter category, and that users are not logged in to your page. If this were the case, I would recommend setting a cookie using the setcookie command, this could be accomplished like this:
if (empty($_COOKIE['hasViewed'])) {
//increment the total number of views in the
//database or wherever we are storing it.
$viewer->incrementViews();
}
//make sure they have a cookie for next time
setcookie("hasViewed", "1", time() + 60*60*24*30);
Note that in this example, the user would be able to cause your view to increment again if they haven't seen the page in 30 days.

script to tell me who, and how many users, are online

In my research to find a way to make PHP tell me how many people are 'online' on my site I've discovered that there are ways to 'estimate' this.
I've chosen to log everything that happens on the site, also for error-management sake, but now i'm stuck at writing my SQL query.
Basicly I have a database with 'IP', 'userid' and 'datetime' and I figured that a query like this would do the trick:
SELECT distinct(IP), datetime
FROM `bigBrother`
WHERE datetime BETWEEN DATE_SUB(NOW(), INTERVAL 3 MINUTE) AND NOW()
The problem is that my site is mostly viewed and used by students on the school network, and well... they all have the same IP.
So the question is, am I doing this right, and can I select two distinct rows from my database, so that I can sort out the registered users (who will have a 'userid' - others will have userid = 0)?
Just use the session id instead of the IP.
Use cookies instead of IP addresses.
PHP makes it very easy with it’s session mechanism. On each you first do a session_start() and then you use the value returned by session_id() as a identifier of the visitor that you can put in your database.
I created a system for a school site that asked for this feature as well and here's how i did it.
I had a table of users, in that table there was a field called "online_time"
On every page a function was called if the user was logged in that updated the "online_time" to the current time of that user. (unixtime)
Then i had an "Who is online" function that looked at the "online_time" and displayed all the users with the online time of the last 5 minutes.
EDIT to the comment:
You could make the same function save the session id in another table and the time it was saved. The session id is unique to that user browsing, so you could get the number of session id's active within the last 5 minutes.
session_id()

Categories