ずっと前session_set_save_handler()を使ってセッション制御を行いました。
当時はそれぞれの処理にいちいち関数を設定するという素敵な構造でしたが、PHP5.4からはインターフェイスを使ったまともな設計ができるようになっています。
SessionHandlerInterfaceインターフェイスを使って書き直してみましょう。
というかSessionHandlerクラスが実装されたので、前のやつをそのまま使うとCannot redeclareのFatal errorになってしまいます。
テーブル作成。
ついでにmysql_connectなどの非推奨なものも外しています。
ずいぶんすっきりしました。
なおidの32桁というのはセッションID生成関数のデフォルト、session.hash_function=0の場合の最大値です。
違う生成方法を用いている場合は桁数を合わせましょう。
write()の第二引数に入ってくるデータはセッションをシリアライズしたものですが、通常のserialize()ではなくsession_encode()という関数が使われています。
見た目は似ていますが互換性はないので注意しましょう。
あとどうでもいいけど、SessionHandlerInterface::gc()の引数はstringになっていますが実際はintでした。
当時はそれぞれの処理にいちいち関数を設定するという素敵な構造でしたが、PHP5.4からはインターフェイスを使ったまともな設計ができるようになっています。
SessionHandlerInterfaceインターフェイスを使って書き直してみましょう。
というかSessionHandlerクラスが実装されたので、前のやつをそのまま使うとCannot redeclareのFatal errorになってしまいます。
テーブル作成。
CREATE TABLE `user_session` ( `id` varchar(32) NOT NULL, `data` text, `regist_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8本体。
<?php
class MySessionHandler implements SessionHandlerInterface{
//セッションテーブルの定義
private $sessionDsn = 'mysql:dbname=session;host=localhost';
private $sessionUser = 'testuser';
private $sessionPass = 'testpass';
//PDO
private $session;
//SQL
private $sqlRead = 'SELECT data FROM user_session WHERE id = :id';
private $sqlWrite = 'INSERT INTO user_session (id, data) VALUES (:id, :data) ON DUPLICATE KEY UPDATE data=:data';
private $sqlGc = 'DELETE FROM user_session WHERE regist_date < NOW() - INTERVAL :second SECOND';
private $sqlDestroy= 'DELETE FROM user_session WHERE id = :id';
/**
* @Override
* セッションを開始した
* @param String セッション保存パス
* @param String セッション名
* @return boolean
*/
function open($save_path, $session_name){
//DB接続
$this->session = new PDO($this->sessionDsn, $this->sessionUser, $this->sessionPass);
return true;
}
/**
* @Override
* セッションを閉じる
* @return boolean true
*/
function close(){
$this->session = null;
return true;
}
/**
* @Override
* セッション読み込み
* @param String セッションID
* @return String セッションの内容
*/
function read($id){
$smt = $this->session->prepare($this->sqlRead);
$smt->bindParam(':id', $id, PDO::PARAM_STR);
if(!$smt->execute()){return '';}
return $smt->fetchColumn(0);
}
/**
* @Override
* セッション書き込み
* @param String セッションID
* @param String 保存内容
* @return boolean
*/
function write($id, $data ){
$smt = $this->session->prepare($this->sqlWrite);
$smt->bindParam(':id', $id, PDO::PARAM_STR);
$smt->bindParam(':data', $data, PDO::PARAM_STR);
return $smt->execute();
}
/**
* @Override
* セッション削除
* @param String セッションID
* @return boolean
*/
function destroy($id){
$smt = $this->session->prepare($this->sqlDestroy);
$smt->bindParam(':id', $id, PDO::PARAM_STR);
return $smt->execute();
}
/**
* @Override
* ガベージコレクション
* @param int session.gc_maxlifetime
* @return boolean
*/
function gc($maxlifetime){
$smt = $this->session->prepare($this->sqlGc);
$smt->bindParam(':second', $maxlifetime, PDO::PARAM_INT);
return $smt->execute();
}
}
// セッションハンドラの登録
session_set_save_handler(new MySessionHandler(), true);
// セッションスタート
session_start();
session_regenerate_id(true);
// 以降普段と同じようにセッションを使用可能
$_SESSION['hoge'] = 'fuga';
このようになりました。ついでにmysql_connectなどの非推奨なものも外しています。
ずいぶんすっきりしました。
なおidの32桁というのはセッションID生成関数のデフォルト、session.hash_function=0の場合の最大値です。
違う生成方法を用いている場合は桁数を合わせましょう。
write()の第二引数に入ってくるデータはセッションをシリアライズしたものですが、通常のserialize()ではなくsession_encode()という関数が使われています。
見た目は似ていますが互換性はないので注意しましょう。
あとどうでもいいけど、SessionHandlerInterface::gc()の引数はstringになっていますが実際はintでした。
PR