ユーザー定義のセッション管理を利用するには、Zend_Session::
setSaveHandlerメソッドにセッション保存ハンドラクラスのインスタンスを渡す必要があります。
ini_set("session.save_handler", "user");
Zend_Session::setSaveHandler(new SessionHandler);
Zend_Session::start();
一行目は念のため。php.iniでuserに設定してあるのならばあらためて宣言する必要はありません。
二行目は、setSaveHandlerメソッドにSessionHandlerのインスタンスを渡しています。
DBに対してSession情報を保存するためのメソッドなどを記述するのはこのSessionHandlerクラスです。
(もちろんクラス名はなんでもかまいませんが)
あとはこんな感じで、Zend_Session_SaveHandler_Interfaceを実装したクラスを定義しておきましょう。
何に使われるのかよくわからないメソッドはとりあえずTrueを返すようにしてあります(いいのか?)
Class SessionHandler Implements Zend_Session_SaveHandler_Interface
{
public function __construct(){
}
// 何に使うのかよくわからないのでスルー
public function open($save_path, $name){
return true;
}
// これも何に使うのかよくわからないのでスルー
public function close() {
return true;
}
// セッション読み込み
//
SQLやクエリを投げる関数は自前なので、ここらへんは各環境に合わせて適当に。
public function read($id){
$sql .= "select data from session where session = " . DB::SqlString($id);
if( DB::SelectQuery($sql,$rs) ){
if( $rs->Fetch() ){
// sessionテーブルから指定のsessionの行のdataを返す
return $rs->data;
}
}
return "";
}
//
セッション書き込み
public function write($id, $data){
$sql = " select p_session(" . DB::SqlString($id) . "," . DB::SqlString($data) . ") as result";
if( DB::SelectQuery($sql,$rs) ){
//
新しい接続により、新規にセッションが発行された場合も呼び出されるため、
//
ストアドファンクションで追加と更新に両対応
return true;
}
return false;
}
public function destroy($id){
// セッション破棄
// なんらかのメソッドを使うとコールされる・・はず
$sql .= "delete from session where session = " . DB::SqlString($id);
if( DB::Execute($sql) ){
return true;
}
return false;
}
public function gc($maxlifetime){
// もちろんセッションのガベージコレクタも手動で定義してやらないとダメ
// 期限切れのセッション情報を消すSQLのハズですが、割と適当。
$sql .= "delete from session where updt <= " . DB::SqlString(date("Y/m/d H:i:s", mktime() - $maxlifetime ));
if( DB::Execute($sql) ){
return true;
}
return false;
}
}
・・と、PHP側はこんな感じ。DBのセッション保存テーブル定義はというと
CREATE TABLE session(
session char(32) , -- PHPSESSID
data varchar(8000) ,
--セッションの実データ
rgdt timestamp not
null default now()
, --
登録日(Insert
updt timestamp not
null default now()
--
更新日(Update
);
alter table session add constraint session_pkey primary key (session);
こんな感じ。
PHPSESSIDは32桁なのでchar。
セッションのデータは場合によってはvarcharの限界にぶちあたると思うので、出来ればtext型にしておいた方がいいかも?
おまけ。
public function write($id, $data){
で呼び出されているplpgsqlによるストアドファンクション。MS
SQLServerのTransactSQLみたいな書き方が出来ないのでわざわざ定義。
値を返す必要あるのか?とかツッコミどころ満載ですがそのあたりは割と適当なのであしからず。
上述のセッションデータフィールドをテキストにする場合は下も直す必要アリ。
これ書いた当初は、新規セッションなら1、上書きなら0、とかやりたかったのだろうけど、プログラム側で一切使っていないのです。
まぁ普通にプログラム側からトランザクション使って更新、追加するっていうんでも良いんですが。
create or replace function p_session(id char(32), indata varchar(8000))
returns int as
'
declare
sdata varchar(8000);
ret int;
begin
sdata = '''';
select data into sdata from session where session
= id;
if sdata is not null then
update session set data =
indata , updt = now() where session = id;
ret := 0;
else
insert into session (session,
data ) values (id, indata );
ret := 1;
end if;
return ret;
end;
'
language 'plpgsql'
上述のように、
Zend_Session::start();
でセッションを開始できます。起動ファイルの最初の方に記述しておきましょう。
また、プログラムの終了前には
Zend_Session::writeClose();
も忘れずに。これを記述しないとエラーが吐かれます、っていうかたぶんセッション変数の更新がコミットされません。
必ず実行される、終了処理として記述しておくと良いでしょう。
あとはマニュアルにあるように、startされてからwriteCloseされるまでの処理として
$defaultNamespace = new Zend_Session_Namespace('Default');
$defaultNamespace->numberOfPageRequests++;
・・とか記述してやれば自動的にテーブルが更新されます。
ブラウザとクエリクライアントを開きながら確認してみてください。