session_set_save_handler - Why isn't this code working?
I've been trying to save PHP session data in a MySQL database, but can't get it to work.
For a simple example, here's code that should increment a counter with each visit. I've seen other examples, etc. but can someone please tell me why this code isn't working? (Apache/2.2.11 (Win32) DAV/2 mod_ssl/2.2.11 OpenSSL/0.9.8i PHP/5.2.9 MySQL client version: 5.0.51a)
Here is the mysql database table:
CREATE TABLE IF NOT EXISTS `sessions` (
`session_ID` varchar(32) COLLATE utf8_unicode_ci NOT NULL,
`session_data` mediumblob NOT NULL,
`access` int(10) unsigned NOT NULL,
PRIMARY KEY (`session_ID`),
KEY `access` (`access`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
And the PHP code (just plug in your db credentials):
<?PHP
function mysession_open()
{
global $sdbc; // Session Database Connection
if ($sdbc) {
return true;
} else {
return false;
}
}
functio开发者_开发技巧n mysession_close()
{
global $sdbc;
return mysqli_close($sdbc);
}
function mysession_read($session_id)
{
global $sdbc;
$session_id = mysqli_real_escape_string($sdbc, $session_id);
$sql_sel = "SELECT session_data FROM sessions WHERE session_id = '$session_id'";
$data_sel = mysqli_query($sdbc, $sql_sel);
$row_sel = mysqli_fetch_array($data_sel);
if (isset($row_sel['session_data'])) {
return $row_sel['session_data'];
} else {
return '';
}
}
function mysession_write($session_id, $session_data)
{
global $sdbc;
$access = time();
$session_id = mysqli_real_escape_string($sdbc, $session_id);
$access = mysqli_real_escape_string($sdbc, $access);
$session_data = mysqli_real_escape_string($sdbc, $session_data);
$sql_write = "REPLACE INTO sessions (session_ID, session_data, access) " .
"VALUES ('$session_id', '$session_data', '$access')";
return mysqli_query($sdbc, $sql_write);
}
function mysession_destroy($session_id)
{
global $sdbc;
$session_id = mysqli_real_escape_string($sdbc, $session_id);
return mysqli_query($sdbc, $sql_del);
}
function mysession_gc($max)
{
global $sdbc;
$old = time() - $max;
$old = mysqli_real_escape_string($sdbc, $old);
$sql_old = "DELETE FROM sessions WHERE access < '$old'";
return mysqli_query($sdbc, $sql_old);
}
global $sdbc;
$sdbc = mysqli_connect('localhost', '...', '...', '...') or die('Could not connect to SDBC');
session_set_save_handler('mysession_open','mysession_close','mysession_read','mysession_write','mysession_destroy','mysession_gc');
session_start();
if (isset($_SESSION['counter'])) {
echo "counter is already set and it is " . $_SESSION['counter'] . '<br />';
$_SESSION['counter']++;
} else {
echo "counter is not set. setting to 1<br />";
$_SESSION['counter'] = 1;
}
echo "<br />Dumping SESSION data:<br />";
var_dump($_SESSION);
session_write_close();
?>
Thanks in advance for your help.
If you comment out the session_set_save_handler line of code, it works fine (it increments). But using the save handler it does not.
None of your query calls have any error checking. Instead of blindly assuming the database portion works, do some basic error checking at each stage, e.g:
function mysession_write($session_id, $session_data) {
global $sdbc;
[...snip...]
$stmt = mysqli_query($sdbc, $sql_write);
if ($stmt === FALSE) {
error_log("Failed to write session $session_id: " . mysqli_error($sdbc);
}
return($stmt);
}
There's only way way for a query to succeed, but zillions of ways to fail.
From the manual:
"Warning
As of PHP 5.0.5 the write and close handlers are called after object destruction and therefore cannot use objects or throw exceptions. The object destructors can however use sessions.
It is possible to call session_write_close() from the destructor to solve this chicken and egg problem. "
精彩评论