Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Storing all user activity as session values and saving session values at the end of session

Normally, I would save all user activity, page views and all values by executing a query on each page load, in php.

  • Now I am thinking about storing all these as session values and executing a query at the end of the session. But, I don't know how I can handle this "end of session" event in php.

I thought about a background process which stores all session values just before the session timeout, but I don't know anything about multi-threading methods in php, even though I've heard some circumvention is possible.

  • I would like to determine if user is inactive without a user trigger (like a page load) and save all the session values at the end of session, before the timeout.

This would save some workload on the database engine, in a way like this: A user views many pages, I increase the value in session, insetead of executing a query like

update pageviews set numberofviews=numberofviews+1

on each page load.

  • question is this: "How can I handle an end of session event in php without a user activity?"

Solutions to the actual problem are also appreciated. regardless of the relevance to the question in bold. (I haven't started writing code on this, my question is not about bug fixing.)

Possible solutions:

  • Storing the data in a mysql table which is a memory type and moving records to another table once in a while.
  • Php has a session destroy handler here

I have found out the php session handler functioon but documentation doesn't say anything about if it can have null parameters for callback parameters?

Will I lose standard functionality if I enter null parameters for the $callback parameters?

I only want to change the session $destroy event. I need help on this one, now.

Relevant posts: RP1

like image 820
Uğur Gümüşhan Avatar asked Dec 28 '22 10:12

Uğur Gümüşhan


2 Answers

You can't really use the session_destroy handler since it's only invoked if you explicitly call session_destroy, which won't happen if the user just closes their browser and ends the session. Since there is no way of capturing the end of session "event" in that scenario, you'll have to instead do some sort of periodic checking to see if the session has been idle for a given period of time. The simplest way to do this is create a field in your session that holds the last access time, then create a script which periodically (either via cron or triggered off some other functionality in your PHP scripts) checks that field for all active sessions and, for any which have a timestamp older than xx seconds, run your update query.

Note that in order to do this using standard PHP sessions which are stored on the file system you'll have to actually open the files and parse them directly. An alternative is to store the sessions in the database but that's probably not what you want to do given the fact you're trying to reduce load on the db.

One other possibility which isn't quite as development-intensive is:

  1. Add a last-accessed timestamp to your session
  2. Check that timestamp each time you update the session
  3. If the timestamp is older than xx seconds run the update query on the db and set the timestamp to the current time.

That way you're only updating the database every so often instead of every page load. The downside to this approach of course is that unless the last activity on the session corresponds exactly with a time interval which invokes the update function, you may not store the most up-to-date session info in the db.

like image 85
TheOx Avatar answered Jan 14 '23 06:01

TheOx


This is not what the sessions were created for, so what you are trying to achieve isn't possible with session mechanics alone.

With standard PHP sessions your options are somewhat limited and depend on session storage:

  1. By default sessions are stored in files. If you disable session garbage collection you can run a cron job that will parse session files older than the time you define. It's not perfect, but by far the simplest. Also file sessions suck - write every request.
  2. Sessions in Memcached. With no good method of fetching records older than x and the fact that Memcached will just drop data when it expires not much can be done here.
  3. Sessions in DB - you already have an update every request.

So your options with standard sessions are limited at best. My recommendation: replace the standard session with your own, but that means you will no longer be accessing session via $_SESSION and will require you to rewrite a lot of your code.

I have replaced the regular session with a singleton that stores session data in APC/Memcached as well as in DB. Session data is saved in DB only if I request it (Session::persistentStore($key,$value)) or if during handling of the request APC/Memcached stored session data indicates it wasn't written for a long enough time. This limits number of writes a lot. With this replacement you'd be just forcing session save from DB side: fetch session ids of sessions that haven't been updated for x minutes from db, fetch info from APC/Memcached for each of those and if there is no update info there either (indicating session will end soon) save it to db.

like image 40
c2h5oh Avatar answered Jan 14 '23 08:01

c2h5oh