PHPのセッション管理をMysqlで行ったときのよく分からない不具合
CREATE TABLE session` ( `id` CHAR(32) NOT NULL, `data` TEXT, `update` INT(10) DEFAULT 0, PRIMARY KEY (`id`) ) TYPE=MyISAM;
という感じでセッション管理用のテーブルをつくって、
<?php class mySession { var $_name; var $_path; function __constructor() { $this->mySession(); } function mySession() { } function start() { session_set_save_handler( array(&$this, 'open'), array(&$this, 'close'), array(&$this, 'read'), array(&$this, 'write'), array(&$this, 'destroy'), array(&$this, 'gc') ); session_start(); } function open($path, $name) { $this->_path = $path; $this->_name = $name; $this->_db =& Database::getConnection(); } function close(){ return true; } function read($id){ $sql = "SELECT `data` FROM `session` WHERE ``id` = ".$this->_db->quote((string)$id); $result = $this->_db->queryOne($sql); return $result; } function write($id,$data){ $sql = "UPDATE `session` SET `data` = ".$this->_db->quote((string)$data).", `update` = UNIX_TIMESTAMP() WHERE `id` = ".$this->_db->quote((string)$id); if($this->_db->exec($sql)==0){ $sql = "INSERT INTO `session` (`id`, `data`, `update`) VALUES(".$this->_db->quote((string)$id).",".$this->_db->quote((string)$data).", UNIX_TIMESTAMP())"; $this->_db->exec($sql); } return true; } function destroy($id){ $sql = "DELETE FROM `session` WHERE `id` = ".$this->_db->quote((string)$id); return $this->_db->exec($sql); } function gc($php_ini_maxlife){ $timeout = time()-$php_ini_maxlife; $sql = "DELETE FROM `session` WHERE `update` < ".$this->_db->quote((string)$timeout); return $this->_db->exec($sql); } } $session = new mySession() $session->start(); $_SESSION['hoge'] = 'セッションのデータ';
みたいな感じでいけるんじゃないかと思ってやってみてるんですが、何故だかセッション内のデータが保持されない。
ちょっと調べると、mysqlに保存されるデータが文字化けを起こしている模様。
多分PHPのセッションは自動的にデータをserialize()/unserialize()してるんだと思いますが、その辺で発生している様子もなく、DBに保存したときに文字化けを起こしているようです。
とりあえず、自分の所為という可能性も捨てきれぬまま消極的対策。
<?php function read($id){ $sql = "SELECT `data` FROM `session` WHERE ``id` = ".$this->_db->quote((string)$id); $result = $this->_db->queryOne($sql); return base64_decode($result); } function write($id,$data){ $data = base64_encode($data); $sql = "UPDATE `session` SET `data` = ".$this->_db->quote((string)$data).", `update` = UNIX_TIMESTAMP() WHERE `id` = ".$this->_db->quote((string)$id); if($this->_db->exec($sql)==0){ $sql = "INSERT INTO `session` (`id`, `data`, `update`) VALUES(".$this->_db->quote((string)$id).",".$this->_db->quote((string)$data).", UNIX_TIMESTAMP())"; $this->_db->exec($sql); } return true; }
ということで、base64_decode/base64_encode(というか日本語以外になればなんでもいいんですが)をread/writeに挟んで文字化け対策。
ていうか原因がまったく分からないんですが知ってるエロいひとがいたら教えてください。