Basically, you need some custom session management.
http://www.php.net/session
It's possible, for instance, to store all of your session data in a database.
Then it would be trivial to query the database for the existence of a session, and find out if a user is logged in.
Say I have a session variable like this:
$_SESSION['USER_ID']
If this variable exists, then I know a login is active for that user. The session data itself is stored in a flat text file by default, but, I can set up a custom session handler using PHP's session_set_save_handler() function. Text files aren't very efficient to query, so I can set up sessions to be stored in a database.
My own custom session handler looks something like this:
Code:
<?php
class session {
public static function setHandler()
{
session_set_save_handler(
array('session', 'open'),
array('session', 'close'),
array('session', 'read'),
array('session', 'write'),
array('session', 'destroy'),
array('session', 'garbageCollection')
);
}
public static function open($save_path, $session_name)
{
return true;
}
public static function close()
{
return true;
}
public static function read($session_id)
{
$query = db::query(
"SELECT `session_data`
FROM `sessions`
WHERE `session_id` = '{$session_id}'
LIMIT 1"
);
return(
(db::numRows($query))?
stripslashes(db::result($query))
:
null
);
}
public static function write($session_id, $session_data)
{
if (db::numRows("SELECT * FROM `sessions` WHERE `session_id` = '{$session_id}'"))
{
db::query(
"UPDATE `sessions`
SET `session_data` = '".addslashes($session_data)."',
`last_accessed` = NOW()
WHERE `session_id` = '{$session_id}'"
);
}
else
{
db::query(
"INSERT
INTO `sessions`
VALUES (
'{$session_id}',
'".addslashes($session_data)."',
NOW()
)"
);
}
}
public static function destroy($session_id)
{
db::query(
"DELETE
FROM `sessions`
WHERE `session_id` = '{$session_id}'"
);
}
public static function garbageCollection($lifetime)
{
db::query(
"DELETE
FROM `sessions`
WHERE UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(`last_accessed`) > {$lifetime}"
);
}
public static function name()
{
return session_name();
}
public static function id()
{
return session_id();
}
}
?>
To use that, you'd call session::setHandler(); before calling session_start();
You'd also need PHP 5 to use my code verbatim, but it'd be trivial to make it work with PHP 4, just remove "public static" from before each of the function definitions.
That goes with the following MySQL database:
Code:
CREATE TABLE `sessions` (
`session_id` varchar(50) NOT NULL default '',
`session_data` text NOT NULL,
`last_accessed` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
PRIMARY KEY (`session_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
If I want to find out if a user is already logged in, I'd do a query like this:
Code:
$query = db::query(
"SELECT `session_id`
FROM `sessions`
WHERE `session_data` LIKE '%\"USER_ID\";s:".strlen($user_id).":\"{$user_id}\"%'
LIMIT 1"
);
If I get a hit, the user already has an active session.
The last thing you want to do is to increase garbage collection probability, otherwise a session could get stuck in an active state and the user could potentially get locked out of their account.
You'll want to tweak the following two INI directives:
session.gc_probability AND session.gc_maxlifetime
More information about those directives is available at
http://www.php.net/session
HTH!
Regards,
Rich
--
Author,
Beginning CSS: Cascading Style Sheets For Web Design
CSS Instant Results
http://www.catb.org/~esr/faqs/smart-questions.html