How Do You Build A Who's On Application?
One question I see a lot of is folks wanting to build a "Who's On" function into their web sites. In its most basic form such a thing is mostly just an "oooh cool" kind of feel-good thing that doesn't accomplish a lot. However with very little effort you can store invaluable nuggets of information.
Exactly what those valuable things are for each individual site varies, and is beyond the scope of this article. However, we'll lay down the basic framework here and you can easily add your own goodies later on your own.
The first thing to do is to look at the code, which as you'll see needs its own window. It is liberally commented and those comments alone may be enough to get you going without reading any further. Still, we'll follow along here with some additional discussion; starting at the top.
- Lines 1-5: This CFAPPLICATION statement really belongs in your Application.cfm. As a rule this tag should only be used once in the public side of your site, although there are certain exceptions to this. The CFAPPLICATION statement is only included here for the sake of a complete, working code sample. Note also that session management has not been enabled here, but only because it is not necessary in this code example.
- Lines 9-12: Some default parameters need to be set up here. variables.SessionLasts is the amount of time in minutes we have decided a session will last. Any visitors whose inactivity exceeds this amount will be removed from the array of visitors we'll build. variables.RightNow is simply a date and time value set into an acceptable visual format.
- Lines 16-20: All of our Who's On information will be stored in an application-scoped two-dimensional array. If the array has not already been initialized, the code in this block will do so. Note that, strictly speaking, when using CFLOCK around a statement that determines if a variable has been defined, you only need a READONLY type lock. However if the variable has not been defined, you then have to set a separate EXCLUSIVE lock (outside of the first lock!) to write the variable. This necessitates setting a flag variable and, when all is said and done I'd rather just use an exclusive lock and move on.
Finally note that if you are using ColdFusion 6+ it is only necessary to lock variables to protect against race conditions. Since this is one of those times (a race condition can result if two users hit it at almost the same time), this CFLOCK is not an option if you are writing for ColdFusion 6+.
- Lines 24-39: This code runs a series of tests to determine the exact url that the visitor is sitting on, including whether or not the connection is secure, the server port (if its not the standard port 80) and all url parameters.
- Line 43: We're using the key pair to identify this visitor in this basic application. However if you log in visitors to your site a great supplement to this would be the user ID number, which you could then use for all sorts of useful things.
- Line 51: With regard to the above comments on race conditions, this CFLOCK is also not optional, as a race condition could result if the remaining code is not locked. For example, if a new user were to show up, their information will be appended to this array. However if two users show up and read the array size at the same time, one user will get input into the array... and the other will see your web site crash since they are working off the wrong visitor count at the instant they tried to execute this code.
- Line 55: The first thing we have to find out is if the array has any elements - a rare condition that will occur at least once when the array is initialized. If it doesn't have any elements we want to skip the entire process that covers the next 60+ lines, mostly because running the sort of tests we will on an empty array will cause ColdFusion to crash and burn.
- Lines 59-98: What is the pupose of this code block? We need to run through what we already have stored in this in-memory database. Some visitors will be returning, and will need their records updated with the most recent timestamps, pages visited etc. Others will have expired and need to be removed. We're accomplishing both processes in this loop.
- Lines 73-77: This test runs a DateCompare() test on the last visit time stored in the array. If the interval between the last visit and the current time is longer than the value we decided to place in variables.SessionLasts, the value that will be returned to us will be -1, which will be used as a flag to kill this expired array element in the next code bit below.
- Lines 78-97: This section will take the value returned to us by the expiration test immediately above. If the session has expired then the array element will be deleted and the count of array items will be decremented, so our loop (which depends on an accurate understanding of how many elements it has to loop over) won't go haywire on us.
If the element has not expired but its found to match up with the current visitor's info, then the last portion of this code block updates that element in the array with current information.
- Lines 104-114: After scrubbing the array clean of expired entries, and checking to see if this is a current visitor who needs to be updated, the last thing to do if neither of the above conditions are true is to add this new visitor to the list of Who's On. This next-to-last bit first determines whether or not an update occurred (based on whether variables.ItemRemade was set to "Y" on Line 95), and if it hasn't, creates a new array item with fresh data.
- Line 116: Last but not necessarily least, we cfdump out our application variable structure so we can see what it is we've collected. Naturally in the real world you wouldn't do this, and its use here is only as a convenience. In the real world your Who's On display would be locked up behind a password access, and quite probably would display a number of more fancy things, derived from the data you collect.
So thats the code. How do we call it? I personally call mine as an include file from with my Application.cfm.
So what about those nifty nuggets of information alluded to earlier? The stuff that would allow you to those "fancy things" mentioned above? You add more information by simply adding elements to your array, and putting in whatever ColdFusion allows you to put in. We used four items in this basic example, but you can have as many as you like. One thing to consider would be an arrival time, which you stamp when the item is created and never update. This could let you calculate a rough session duration on your Who's On display.
Another thing that could be useful is to track a user's Login ID, which you can use to pull information out of your user database when you build a for-real, grownup who's on display for your site's admin area. Personally, I like to display user access level, and display their email address as a live link to make it easy for me to email them if I see a reason to contact them.
Whatever it is you do, it'll very likely be much more extensive, and hence much more useful. Have at it and have fun with it.