PHP logic to compare a session id in shopping cart? - php

I have created a shopping cart on a project for college using PHP, and I can add to cart with a link from the items, this updates my cart table in my database which i then print out.
I want to be able to delete eveything in the table once the user has exited the page or closed their browser (i presume this is when the session id changes).but i cant think of the logic to doing this?
cheers

Usually this is done keeping track of the user's last activity.
Every time any user opens a page a last_log entry for the all the logged users are checked on the database. If the last time one user did something is older than N minutes, then the session is made to expire. You can then log the user out and remove its items.
You might rise the question: "What happens if there's no user currently opening pages? There will be no one to trigger the execution of the code". In that case there's also no one interested to know the content of any shopping cart and the table can remain filled. To solve this problem, with this solution, you might need a scheduled task running on the server.
Here's a summary of the steps:
...
Retrieve the list of expired sessions since the last check
For every expired session
Remove the items from the shopping cart
Update the last_log entry for the current user
...
Checking all the users sounds like an expensive operation, but you have to consider few things:
One SELECT to find who to log out (if you need it) and one UDPATE to log them out
The SQL is optimized to update only a subset of all possible users
The table will have an index on the relevant fields to speed up the process
How many users would you have currently active in the session timeout window? A really worst case scenario would be in the order of 100.000 users in half an hour. Not a big deal for a RDBMS to go through all of them.
Here is a sample SQL (in no particular language):
-- Used to check which user session have expired since the last check
SELECT username FROM session_table WHERE last_log < SUBTRACT(DATE(), 30 MINTUES) AND logged = 'true';
-- Used to log out the users after the timeout
UPDATE session_table SET logged = 'false' WHERE last_log < SUBTRACT(DATE(), 30 MINTUES) AND logged = 'true';
-- Used to update the last_log entry for the current user
UPDATE session_table SET last_log = DATE() WHERE user_id = "...";
You can do this using cookies or sessions, but I prefer the DB as it avoids to deal with PHP session tracking and allows you to do more complex things if, for example, you want to keep a "saved for later" or "draft" item list.
UPDATE: I made some clarifications about the logid and the DB/SQL part.

You can "clear" your table using some time-logic.
For instance, when you user come back to your page (you can verify it using $_SESSION, $_COOKIE, $REMOTE_ADDRESS and so on), if that 'second' view is after, maybe 2 days, you can 'clear' those datas. Or, you can create a 'job' inside your database to check when was the last time the user access your webpage (column 'last_login') and again, delete any product inside the card, which that user added.

use JavaScript to send an AJAX request to your server when user close browser you can check with Javascript event "onBeforeUnload". This way the script will ensure the session and DB record are only deleted when the user is leaving the website.
<script type="text/javascript">
$(window).on('beforeunload', function() {
$.ajax({
url: /yourfileDeleteSession.php
});
});
</script>

Related

How to allow only one session per user?

I am making a platform where you can only access one session per person, to do this, I had to insert in the DB a session id, then, for example:
The user logs in Chrome, at the time of login, in my DB the session id is inserted.
If the same user logs in Firefox, a new session id is inserted, and at the end it compares which was the last id so that only the last person who logged in can have access.
But the problem I have is that, if the user who logged in in Chrome does not make any movement, ie reload the page or click on another, then it stays right there and does not close the session. What I want to do is that when the user logs in on another device or browser, it automatically bounces the first session.
I know that with JS I can call that block of PHP code where I have the validation every certain time, but this would not work 100% because the platform is courses (videos) so if I make the function to run every 5 min example then you can see a course without problem the other person and if I run every 10 seconds I fear that as it sends many requests at once, you have problems with the server. Another question I have is that if I use JS and I set the function with JS then a user who has some knowledge can inspect and delete the JS and then the set code would not be executed or yes?
A more understandable example is what WhatsApp does not let in theory open another session at the same time. Any idea how to solve? Thank you very much.

calculate the time logged in by a user

i want to calculate the time for which the user remains logged in on my site, for example if user A logs in at 10 am and logs off at 10:15 am then store 15 minutes time and if he again logs in then also calculate that time and add to this 15 minutes and shows his total time in the system.
Quick example I can give you.
First add the required field in your database. i.e. In your users table, have a field called 'totalTime' or something.
If you're using SESSIONS, keep a value $_SESSION["start_time"] when the user logs in, and when the user logs out take the difference of the current time subtracted by the start time and add it to the totalTime field in the database for the specified user.
Any variation of that should work.
You could have a loggedIn field in your table, and a totalTime field. When the user logs in, record the time in the loggedIn field. When he logs out, get the logged in time, calculate the difference, and store it in the totalTime field, and zero the loggedIn field.
If the user logs in and the loggedIn field is not zero, the user did not log out, add the difference between the current time and the last loggedIn value can be added to the totalTime (or zero added - you would decide on a policy) and the loggedIn field updated to the new log in time etc.
If you want to collect detailed information about users, and not use simple statistics that google paralytics provide, you have a couple options, none of which are perfect solutions for anything.
Option 1:
You can simply record the time when users click on your page. The issue with this is that there is no way to see how much time a user has spent on your last page. But overall it will provide a good estimate, but will be very costly if yo have over 1000 users.
Option 2:
Record the time when user enters the website, and then have javascript ajax call that will record the time when user either logs out or closes the page. This will work if you allow users to be in a single window only.
Option 3:
Have javascript execute every minute or so and tell database that user is still logged in. Almost all databases can do over 1000 queries like that per second. If you optimize it, change database engine or do anything else you can easily get to 10k-25k queries per second.
Option 3:
If you are charging people money per minute then you can wrap the entire thing in java, or flash. however it is also not very secure.
Bottom line is: There is no perfect way to do it. You will have to hope that users have javascript enabled and track their time using background scripts, or do the whole session thing and hope that users log out. Or Track everything click by click and hope that your algorithm works well enough.
The below solution would be the most efficient one
The log table should have userid, unique_identifier, start_time, end_time
Logging in to the website will add a unique identifier for that session. It can be random number of 12 digits.
A variable $default_duration = 1440; is defined to calculate the session exipry due to inactivity. This variable should be set according to your server settings. 1140 is 1140 seconds (24 minutes), which is the default session exipry time
On user login, lets say a user loggs in by 2PM, the end time is set on login as well, which will be 2.24PM. This will solve the scenario of a user's session expiry due to inactivity.
On each page load, the end time is updated with "Current Time + $default_duration"
If a user clicks on Logout button, the endtime for that session is taken from the current time. This records the exact duration of the user.
Incase if the user logout and logins again, it would have a different "unique identifier" and the log time is updated against it.

User table in database is changed, how to update session?

Currently when the user logs in my site, a (PHP) session is started and his database row is saved in his $_session. I do so because the size of user's data is small for now, and this way I do not have to ask the database for user's data every time I need it.
The problem is that, when I want to add or change something during the development and I touch the database, the session is not updated this way. The user have to logout and login again to update the session. This is good for now since the site is in development phase, but in production this is not desirable.
I wouldn't delete session files, because people are lazy and I would avoid to force them to re-login every time something change in database, and I do not want to reload the session every X minutes. My solution for now is a boolean column inside the user's table, false by default, that I set true when I change the database. Every time a session is continued, session data will be updated if that value becomes true. Anyway this way I have to do a (small) query every time an user continues a session. I do not know if this will be a problem in production.
Is there an alternative / better way to solve my problem?
If I understand the problem correctly, one way to handle this would be every time a user row in the DB is updated that user's session data could be updated as well in PHP.
If it is not the user updating the records (such as an administrator changing a user's permissions) most likely you would want to force a logout of the user. If it is the user updating the records (such as changing information in their user profile) simply updating those values in the session variables may be enough.
In both of these cases you probably also want to provide a message to the user letting them know what happened.

How to limit number of logins at a time?

Hello I have a website. created using php,mysql. I want to set a limit like.. only 10 user can login my website at same time. How can I do that kind of a setting? any body knows the solution kindly help me..
Use a database table to store the number of logged in users but you need to come up with some way of imposing a time limit on those users. I would suggest a field in the table which notes their last activity. When a new user attempts to login you need to apply some logic like this (pseudocode):
if(<10users){
login
} elseif(any of the users have no activity for 30 mins){
remove that user and login
} else {
inform user of no space
}
You would need to update the last activity every time a logged in user visits a new page.
Go read up on sessions in PHP, then write your own session handler - the first time as a learning exercise. Then write your own session handler again, fixing all the bugs from your first attempt and adding in the facility to count active sessions.
Note that the normal behaviour for session handlers is that the session data persists even after the session has timed out - its up to the garbage collector (and optionally the session loader) to clear up session data which is stale.
i would override php session handling and store user sessions in the database. you can find a simple tutorial here: http://www.raditha.com/php/session.php
this way you can simply check if there are more than 10 valid sessions stored in your database table. though you have to think about handling logouts and timeouts, as some standard timeout like 30 minutes might not work well in your application.
If you want 10 user logged on your site, disable the login box if there are more than 10 users logged in.
This presume that you have a table in the db that records the users that are logged in the site. The login procedure will write a new line in the table. The logout procedure will delete it.
Simply count the numbers of rows in this table to determine the number of users.
as answered above you have to maintain a table which will store the number of users who logged in,but whenever the user logs out then decrement that value....whenever a new user logins increment that value by checking it with ur limit

Is my method of auto-redirect-login page correct in PHP?

I have a community site where a user can have many friends. When displaying all of his friends, I want to include whether his friend is online or offline.
My method is, when user logs in, create a session and update the users table, on status column "online". If he click the logout button, then i will set the status to "offline". What if he close his browser without clicking the logout button? Here is what I want to do:
session_start();
if (!isset($_SESSION['LAST_ACTIVITY'])) {
// initiate value
$_SESSION['LAST_ACTIVITY'] = time();
}
if (time() - $_SESSION['LAST_ACTIVITY'] > 3600) {
// last activity is more than 10 minutes ago
session_destroy();
//direct to a php, say this user is idle and thus status = offline
header("location: update_status.php?user=".$_SESSION['username']."&status=offline");
// den redirect them to login page
} else {
// update last activity timestamp
$_SESSION['LAST_ACTIVITY'] = time();
}
Is this an appropriate way?
EDIT:
It would be helpful to see some easy sample code with how to check whenever a user is online and update whenever a user visits a page?
Do I need to include php?user=$_SESSION['userid'] in every link?
Well if you determine whether or not a user is logged out, simply by your online/offline column - then users closing their browser window (without hitting your logout link/button) will still be logged in.
The normal approach here is to keep track of when your users move around your site, storing the last time of when they navigated to a page. Then you set a predefined constant of what makes a user active (say navigating around your page within the last 15 minutes) - and then you use this on your SQL Query to grab every user that is a friend of the visiting person and has been on the site within the last 15 minutes.
In a SQL Query where you store your time as datetime (this is a query for MySQL) this could look something like:
SELECT col1, col2, col3 FROM Users WHERE DATE_ADD(LastActive, INTERVAL 15 MINUTE) > NOW() AND UserIsFriendOfCurrentUser
Of course your query would need adapted to fit your setup better, but hopefully you get the idea.
In my Opinion this will not work. When the User closes the Browser, the code you put here will never be called.
A possible way would be to save the last time the user was active in the database, whenever the User calls a page. If the Users last Activity was longer than say 5 minutes ago, you could count him as offline, and show this to other Users.
I think that phpbb3 does it that way...
Getting an Event when the User closes the Browser is heavy and does not always work.
After the header location redirect, definitely put this line:
die();
Not all user agents (browsers, web spiders, etc) will listen to your redirect header. Killing the script is the only safe way to make sure they don't get the rest of the page.
As far as I understand your solution is the user still marked as online even when the last time the user was on the site is more then 10 minutes ago.
You should save in your database, the last time an user was active on your site. When a user looks then on the list of friends you get also this time and look if that is more then 10 minutes ago, i.e. the friend is inactive.
The best way to do this is to store activity times for logged in users. When they navigate to a page, or perform an action, update their "last activity" time in the database with the current time. If this time falls outside of a threshold (say, 15 minutes), then you can class the user as no longer active.
In our project we use this technique:
every user after login is being associated with session id.
browser sends an "activity-request" with AJAX by timer.
a lightweight server-side script updates last activity in DB, searching
user by session id.
cronjob updates all timed-out users, marking them as offline
(actually session id gets empty), and
executes logout routines for every
user to avoid corrupted data on
business-level layer.
What happens to user?
Until user closes his browser - activity is being updated. After closing the browser user gets timed out and marked as offline. When user tries to reach any location which requires authorization - the first thing we try to do is to find him in DB by session id, and if not - he just can see nothing but login form (i.e. include(); exit();).
Bad thing - tabbed browsers use the same session id for each opened tab in the same window. But our project is a game and multi-users from one browser are not allowed. Actually it's a very rare situation wher 2 or more users try to login from different tabs of one browser...
I see a couple of problems in your code:
if (time() - $_SESSION['LAST_ACTIVITY'] > 3600) {
// last activity is more than 10 minutes ago
session_destroy();
//direct to a php, say this user is idle and thus status = offline
header("location: update_status.php?user=".$_SESSION['username']."&status=offline");
}
In this piece of code you destroy the session and then get the username from the session you just destroyed.
By the way, if I understand your question, you don't get the intended behaviour with this code.
You check if the user is just accessing your site (owner of the session you start) has been idle form more than 10 minutes and, if true, you disconnect him just now that it tries to reenter in the site.
You shouldn't use $_SESSION for storing the last activity time. Every time a user goes to a page, update a column called last_activity with the current time in the users table:
<?php
session_start();
$userId = (int)$_SESSION['user']; // make sure it's an integer
$db->exec('
UPDATE users
SET last_activity = NOW()
WHERE id = ' . $_SESSION['id']
);
//...
When you retrieve your list of friends, add an if statement to check if they are online (this is the MySQL version):
SELECT
u.user_name, u.name, etc,
IF(
UNIX_TIMESTAMP() - UNIX_TIMESTAMP(u.last_activity) < 300,
1, 0
) as online
...
The 300 is seconds so 5 minutes. Adjust this as you see fit. Then your friends can be accessed like so:
$friends = $db->query(/* above SQL */);
foreach($friends as $friend)
{
if($friend['online'] == 1)
// online specific stuff
else
// offline specific stuff
}
Database sessions may be a good way for you to manage who is online and who isn't. Theoretically they should expire on their own. I wrote a how-to on my blog about it, you can read more at http://brennydoogles.wordpress.com/2011/09/06/taking-control-of-your-php-sessions-using-database-sessions/
This also has the added bonus of allowing you to kill a user session remotely if you need to :)

Categories