ID: 20449 Comment by: [EMAIL PROTECTED] Reported By: [EMAIL PROTECTED] Status: Feedback Bug Type: Session related Operating System: redhat 7.3 PHP Version: 4.4.0-dev New Comment:
Ok. I will fix my handler using your suggestions. I'll get back to you after a few hours of letting it work. Josh Previous Comments: ------------------------------------------------------------------------ [2002-11-17 12:40:32] [EMAIL PROTECTED] I'm trying to provide as much as I can. Here is a sample session from the dbase. cart|a:1:{s:9:"161-00084";s:14:"White-Medium|1";}affiliatename|s:0:"";cartposted|s:10:"addProduct"; A quick thought. I use the | as a delimiter to seperate the color-size and quantity. Would my delimiter potentially screw up the unserialize or serialize functions? For multiple products here is a sample session. cart|a:2:{s:9:"117-00717";s:20:"Black-Small_Medium|1";s:9:"117-00875";s:15:"Yellow-Medium|1";}affiliatename|s:0:"";cartposted|s:10:"addProduct"; ------------------------------------------------------------------------ [2002-11-17 12:36:34] [EMAIL PROTECTED] Missed a couple of words in the above. "will randomly be deleted" I meant to write. ------------------------------------------------------------------------ [2002-11-17 12:35:37] [EMAIL PROTECTED] Your handler isn't very good. As far as I can tell you never update the expiry value which means that your sessions will randomly (because the gc hook is called on a probability) after 5400 seconds (90 minutes) after initial creation. A quick fix would be to never expire sessions by setting: session.gc_probability = 0 In your php.ini file. Or, better yet, fix your handler to update the expiry time when writing to a session. This expiry time is supposed to be idle session time, not an absolute the way you have it. I would suggest letting MySQL handle the timestamp and using a schema that looks like this: id char(32) NOT NULL, data text, ts timestamp, PRIMARY KEY (id) And instead of that ugly INSERT/UPDATE thing you have for your write hook, use: $data = addslashes($data); mysql_query("replace into $table (id,data) values('$id','$data')") or error_log("write: ".mysql_error()."\n",3,"/tmp/errors.log"); The gc hook would just be: function gc($max_time) { global $table; mysql_query( "delete from $table where UNIX_TIMESTAMP(ts)<UNIX_TIMESTAMP()-$max_time") or error_log("gc: ".mysql_error()."\n",3,"/tmp/errors.log"); return true; } But try setting gc_probability to 0 just to verify that this is indeed the cause of the lost sessions. If it is, then you need to slap yourself hard as the code is doing exactly what you told it to do. ------------------------------------------------------------------------ [2002-11-17 12:19:36] [EMAIL PROTECTED] I'm reopening this bug as I've provided more feedback. Please yell at me if I'm not doing this right :) ------------------------------------------------------------------------ [2002-11-17 12:17:39] [EMAIL PROTECTED] here is my session save handler. Pretty much taken from phpbuilder.com article. Important to note that I have never seen a mysql error in my php_errors log. <? $GLOBALS["SESS_DBHOST"] = "not shown"; /* database server hostname */ $GLOBALS["SESS_DBNAME"] = "not shown"; /* database name */ $GLOBALS["SESS_DBUSER"] = "not shown"; /* database user */ $GLOBALS["SESS_DBPASS"] = "not shown"; /* database password */ $GLOBALS["SESS_DBH"] = ""; $GLOBALS["SESS_LIFE"] = 5400; function sess_open($save_path, $session_name) { if (!$GLOBALS["SESS_DBH"] = mysql_pconnect($GLOBALS["SESS_DBHOST"], $GLOBALS["SESS_DBUSER"], $GLOBALS["SESS_DBPASS"])) { echo "<li>Can't connect to " . $GLOBALS["SESS_DBHOST"] . " as " . $GLOBALS["SESS_DBUSER"]; echo "<li>MySQL Error: ", mysql_error(); die; } if (! mysql_select_db($GLOBALS["SESS_DBNAME"], $GLOBALS["SESS_DBH"])) { echo "<li>Unable to select database " . $GLOBALS["SESS_DBNAME"]; die; } return true; } function sess_close() { return true; } function sess_read($key) { $qry = "SELECT value FROM sessions WHERE sesskey = '$key' AND expiry > " . time(); $qid = mysql_query($qry, $GLOBALS["SESS_DBH"]); if (list($value) = mysql_fetch_row($qid)) { return $value; } return ""; } function sess_write($key, $val) { $expiry = time() + $GLOBALS["SESS_LIFE"]; $value = addslashes($val); $qry = "INSERT INTO sessions VALUES ('$key', $expiry, '$value')"; $qid = mysql_query($qry, $GLOBALS["SESS_DBH"]); if (! $qid) { $qry = "UPDATE sessions SET expiry = $expiry, value = '$value' WHERE sesskey = '$key' AND expiry > " . time(); $qid = mysql_query($qry, $GLOBALS["SESS_DBH"]); } return $qid; } function sess_destroy($key) { $qry = "DELETE FROM sessions WHERE sesskey = '$key'"; $qid = mysql_query($qry, $GLOBALS["SESS_DBH"]); return $qid; } function sess_gc($maxlifetime) { $qry = "DELETE FROM sessions WHERE expiry < " . time(); $qid = mysql_query($qry, $GLOBALS["SESS_DBH"]); return mysql_affected_rows($GLOBALS["SESS_DBH"]); } //now that we have defined everything, set the save handler session_set_save_handler( "sess_open", "sess_close", "sess_read", "sess_write", "sess_destroy", "sess_gc"); ?> ------------------------------------------------------------------------ The remainder of the comments for this report are too long. To view the rest of the comments, please view the bug report online at http://bugs.php.net/20449 -- Edit this bug report at http://bugs.php.net/?id=20449&edit=1