I am having problem with session destroy. I am running a script called logout.php in that file I am destroying user session also I am executing a query which will delete my shopping bag. This is working properly but when I closed the browser or session is automatically destroy after sometime , that time I have to delete my shopping bag off course in this situation logout.php will not call. So how can I achieve this .
logout.php :-
<?php
include_once('functions/config.php');
session_start();
$sql = "DELETE FROM baskets WHERE member_id = '".$_SESSION['memid']."' ";
mysql_query($sql);
session_destroy();
header('location:index.php')
?>
I have two answers for this questions:
1) you can clear your shopping bag using javascript event window.onbeforeunload
example:
window.onbeforeunload= function(){
// your ajax call to clear shopping bag
}
2)I will recommend this option:
You can clear users shopping bag on his login.
There is no way to write code that you can safely assume that it's called when a session is destroyed.
Easiest way to do what you want is to set a "last accessed" timestamp on your basket that you update on every access, and then run a cron job (scheduled job) every hour or so that deletes all baskets that haven't been accessed in, let's say, 6 hours or more. That won't delete it at the same time as the session times out, but will keep old baskets out of the database in the long run.
Are you sure you want to clean the shopping bag when (for example) the users' browser closes? You could give a warning like 'You have not logged out correctly last time, do you want to continue shopping or start fresh?' , something like that.
HTTP is a stateless protocol, so you can't tell when a browser actually closes. In my opinion you need to work with session timeouts, so that after a period of time has passed the shopping bag gets cleared anyway unless there still is user activity.
Hope that helps.
Related
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>
I'm working on a "flash website". In this program, I'd like to add an "Online Users" list, which relies on sessions: A session is started when a user logs in, and the user is marked as Online in the database. As soon as the logs out or closes the browser, the user is marked as Offline in the database.
I know that running some functions when the browser is closed will require Javascript, and it's not safe either: If the browser were to crash, the functions wouldn't run. That's why I've settled for the database updating if the user logs out or if the user's session times out.
I've been looking up session timeouts, and ran into this, along with many others like it marked as duplicates: How do I expire a PHP session after 30 minutes?
The problem with the answer's method is; It's a conditional sentence that checks if the user's last activity was X seconds ago, and if there was no activity, it times out. Useful in some websites, but useless for the Online Users list, since it updateds when a new request is sent, and since there won't be any requests after the user closes the browser.
Also mentioned in other answers is the use of session.gc_maxlifetime and session.cookie_lifetime, but the Best answer states that using them is a bad idea; One doesn't destroy the session, just the cookies, and the other is "cost-intensive".
What I want is the user to time out and the database to update and mark the user as Offline without using the If-Conditional sentence, or maybe with using a different If-conditional sentence that only has to be used once when the user logs in, like a timer or something, and whenever a request is sent, the timer restarts...those are just my ideas so far on how to solve this problem.
But, how do I do this? I'm sorry if the answer is something very simple and obvious, I'm very new to PHP.
Edit: Long Story Short:
I want to run a function after the user closes his browser, or is inactive for 20 minutes.
Clarification...
I want to update the database after 20 minutes of inactivity even if the browser has been closed.
I want to update the database after 20 minutes of the browser being
closed.
I don't think this is really possible to do with browsers being closed (reliably). If they click the logout button you can obviously run some code to mark the user as logged out. You can specify how long a session is good for with the functions you mentioned but all this does is makes the cookie be deleted on the client side, it doesn't trigger anything on the server side.
About the only thing you can do is track the time of the user's last activity and if they haven't had activity in a while assume they are gone. So just add a field to your user table and store a datetime or unix timestamp of their last activity. Then you can either run a cron job every few minutes that marks users as logged out or you can simply modify your SQL query to pull only users that have a last activity less than 20 minutes ago.
You can do this with the help of a online users table with last active field,
window.setInterval(function() {
$.ajax({
url: "http://yourdomain/updateLastactive/?uid=" + User_ID,
success: function(data) {
}
});
}, 5000); // 5 seconds
This page will update the current time-stamp as last active for that user
Then on online users query you can do like below,
SELECT UID FROM ONLINE_USERS WHERE LAST_ACTIVE > DATE_SUB(NOW(), INTERVAL 30 MINUTE));
if (!isset($_SESSION['CREATED'])) {
$_SESSION['CREATED'] = time();
} else if (time() - $_SESSION['CREATED'] > 1800) {
// session started more than 30 minutes ago
session_regenerate_id(true); // change session ID for the current session an invalidate old session ID
$_SESSION['CREATED'] = time(); // update creation time
}
Also read this
http://php.net/manual/en/session.configuration.php#ini.session.gc-maxlifetime
You want to catch the event by using the information here:
How to capture the browser window close event?
You will then need a page on the server that you call in that event handler with the sessionID.
That page calls a local script, page, or service that you set up to delay 20 minutes and expire the session. If you want to restart the clock if the user revisites before expiration, you will need to include a way to interrupt or cancel that script's process and you will need to retain the SessionID in a cookie which will need to be looked for upon every page load. If the cookie's SessionID is found and matches, the timeout gets interrupted/stopped (if it's still going). If it already completed, a new SessionID will need to be issued.
If you have a lot of these cancellations at the same time, you will instead queue them up on the server and have a process periodically check the queue and expire them as needed.
The way most sites avoid all this is to set a 30 minute or whatever session timeout that is enforced whether the visitor is active or not.
The easiest way to do this is to write a MySQL stored procedure that looks at the session timestamp and deletes the session data when it is > 20min old. You can also do it as an external cron job, but a stored procedure would be better.
In addition, you need to refresh the session timestamp every time the user connects.
If you want to make sure you don't delete a session when the user still has your 'page' open, then some background JavaScript refresh to your site will function as a keep-alive. Note that if the user closes the 'window' or 'tab', it will be the same as the whole browser being closed - I'm not sure you can do anything about this.
Of course, you to do this, you need to store your sessions in MySQL.
TL;DR
MySQL stored procedure or cron job deletes session if session_timestamp > 20min
Client-side Javascript does ajax refreshes to keep session open
Session timestamp updated every time the 'page' is requested (browser or ajax).
I need all active sessions to be destroyed when I call a certain function. This function when called needs to destory all sessions NOT immediately but after exactly 30 seconds. Even if the user leaves the page where the session was called before the 30 seconds, his browser should still be cleared of all sessions so when he comes back to the site none of those sessions will be active.
Is this possible? If so how would one go about writing such a function?
EDIT
As for why I need this, I have a shopping cart script that when submitted takes the user to paypal to process payment. If I destroy all sessions when the submit button on that payment form is clicked, I can;t pass all the form data onto paypal. If I don't destroy all sessions, when the user comes back to the site the shopping cart is still filled with the contents he purchased before.
I need the cart to be empty when the user comes back. I figured 30 seconds will give the user ample time to go to the paypal page by which point my cart script has already sent all necessary info to paypal. And then destroying all sessions is safe without fearing disruption to service.
So what I need is sort of a timer script that will work on the server side and will destroy the sessions even when the user is no longer on that page.
See http://bytes.com/topic/php/answers/4134-when-how-php-session-expire-can-i-set-minutes-inactivity
Ok, so nevermind my hairbrained sleep() approach.
Set a flag in the session, before you send them over to paypal. Check this flag and clear the session/cart if it's set.
I need a php code that will run a query after a specific session is going to expire,
if(!isset($_SESSION['test'])) query;
something like that but does work with session expire.
The problem you'll run into: a session doesn't just expire by itself, a session is expired on the next page load if the user waited too long. As there's no communication between browser and server between requests (user action), the server won't know if e.g. the user just closed the browser (or is doing the dishes while the website remains open).
So I guess there's nothing wrong with your code as it'll tell you if the sessin is expired on the next pageload (as long as there is a next pageload :)).
If you really need to make sure, the query runs after a session expired, I guess you'll have to save your sessions to a database and run a "cleanup"-script on each pageload to run your query and get rid of expired sessions. (e.g. save "lastUserAction" and compare that to whatever your session-limit is)
I would suggest to save the date you created the session in the database and check if the session expires like:
if($db->checkExpiredSession('test') == true) {
$db->query('...');
}
Just a thought.
I'm trying to log users out when the user's session timeout happens. Logging users out - in my case - requires modifying the user's "online" status in a database.
I was thinking that I might be able to use the observer pattern to make something that would monitor the state of the user session and trigger a callback when the session expires - which would preserve the user's name so we can update the db. I'm not exactly sure where to begin on the session side. Can I tie a callback to the session's timeout?
are these things built into any available pear or zend session packages? I will use whatever I have to to make this happen!
UPDATE # 16:33:
What if you have a system where users can interact with each other (but they can only interact with online users)? The user needs to know which other users are online currently.
If we simply check to see if the session is still alive on each page refresh, then after a timeout, the user is sent to a non-logged in page, but they are still listed as online in the system.
That method would be fine except that when we timeout the session, we lose the information about the user which could be used to log them out.
UPDATE #16:56:
right. Thanks. I agree...sort of ugly. I already have some slow polling of the server happening, so it would be quite easy to implement that method. It just seems like such a useful feature for a session handling package. Zend and PEAR both have session packages.
Take the simplest case first. Suppose you have 1 user on your system, and you want their session to timeout, and you want accurate reporting of their status. The user has not been to a page in 12 minutes, and your session timeout is set to 10 minutes. One of two things will happen. Either they will visit again in a short while, or they will not. If they don't visit again, how will the system ever run code to update their timeout status? The only way* is to have a separate process initiate a status update function for all users who are currently in status "in session".
Every time a user hits your site, update a variable in the database that relates their session to the last accessed time. Then create a cron job that runs every minute. It calls a simple function to check session statuses. Any sessions older than the timeout period are set to status "timed out". (You should also clean up the table after timed out sessions have sat for a while). If you ever want a report on the number of people logged in, query for all records that have a last accessed time later than the timeout interval start.
"*" There are other ways, but for the purposes of a simple web application, it's not really necessary. If you have something more complex than a simple web app, update your question to reflect the specific need.
Whenever a user hits a page, mark that time in the database, call this column LastAccessed. When the user clicks on the Logout portion of your site, you can set this value to null. When writing your query to find a list of users who are currently logged in, do the following:
SELECT * FROM Users WHERE LoggedIn=1 AND LastAccess > DATEADD(Minute,-20.GETDATE())
Which would return the users who still have an active session. Pardon the SQL which probably doesn't work with MySQL/PHP, but this should give you a general idea.
Why do you want to do this? The common approach is to check on every request sent by the user if the timeout has expired. Of course that means that the status in your db is not up to date, because the user is still shown as logged in, even though the timeout has been reached.
But for practical purposes that usually doesn't matter.
Ugly but maybe workable suggestion:
Add an asynchronous keep-alive requester to pages, that updates their last-active timestamp. You can then have a cron job that marks users as offline if they have a last-active timestamp more than 20 seconds old. Setting that cron job to run every minute would do the trick. I'm not sure there's a way to trigger something to happen when a user's session times-out, or closes their browser.
My first thought is that you could create a custom session handler that interprets being logged in as having an active session.
For some examples on creating a custom session handler see http://www.daniweb.com/code/snippet43.html and read the PHP doc http://ca.php.net/manual/en/function.session-set-save-handler.php
I know this might be a older question but the "best" answer to your question is found here:
http://www.codeguru.com/forum/archive/index.php/t-372050.html
Here is what it says:
The php.ini file contains a setting called sesison.save_path, this determines where PHP puts files which contain the session data. Once a session has become stale, it will be deleted by PHP during the next garbage collection. Hence, a test for the presence of a fiel for that session should be adequate to determine whether the session is still valid.
$session_id = 'session_id';
$save_path = ini_get('session.save_path');
if (! $save_path) {
$save_path = '.'; // if this vlaue is blank, it defaults to the current directory
}
if (file_exists($save_path . '/sess_' $session_id)) {
unlink($session_id); // or whatever your file is called
}