hogehoge foobar Blog Style Beta

Web,Mac,Linux,JavaScript,Perl,PHP,RegExp,Git,Vim,Redmineなど技術的なことのメモや、ちょっと便利そうなものの紹介をしています。

PHPセッションをDBで管理 - PHPセッション管理のコールバック関数を設定編

前回エントリ PHPセッションをDBで管理 - OracleでのAutoIncrement用テーブルを作成編 の続きです。
前回はOracleでセッション管理用のテーブルを作成するところまで行ないました。
今回は、そのテーブルを使って実際にPHPからセッション管理を行うのをやってみます。

※参考にさせてもらったページ

PHPのセッションをDB管理するにあたり、全体的な部分は「Web Artisan Blog」、OracleでAutoIncrementについては「イイ!! プログラミング Blog」、OracleのCLOBの更新方法等については「あるプログラマーのつぶやき」を参考にさせていただきました。

PHPセッション管理のコールバック関数の作成〜設定

PHPのセッションはデフォルトでファイルを使用するようになっているため、まずは設定を変更します。これはphp.iniまたはini_setで「session.save_handler」を「user」に設定すればOKです。

次に実際にセッション管理用の関数を定義します。
定義する関数としては、以下のようなものになります。
(表の関数名は当エントリのサンプルコードの関数名です。実際には任意の名前を付けられます。)

関数名 用途
sess_open セッションのオープン時に実行される関数,コンストラクタのようなもの
sess_close セッションのクローズ時に実行される関数,デストラクタのようなもの
sess_read セッションの読み込み時に実行される関数,セッションIDをキーにしてセッション情報を取得する処理を書く
sess_write セッションの書き込み時に実行される関数,セッションIDをキーにしてセッション情報を更新する処理を書く
sess_destroy セッション破棄時に実行される関数,セッションIDをキーにしてセッション情報を削除する処理を書く
sess_clean ガベージコレクション実行時に実行される関数,maxlifetime以上経過しているセッションを削除する処理を書く

定義した関数については「session_set_save_handler」で、セッション管理用コールバック関数として設定をします。

設定の例
<?php
session_set_save_handler('sess_open','sess_close','sess_read','sess_write','sess_destroy','sess_clean');
?>

ここまで出来たら、あとは普通に「session_start();」でセッション開始したり、「$foo = $_SESSION['foo'];」「$_SESSION['bar'] = $bar;」とかでセッションの読み書きが出来るようになります。
もちろんセッション情報はDBに書き込まれます。

下記に、今回作成したサンプルコードを書いておきます。

今回作成したサンプルコード

※エラー制御とかをぶっちぎっているのはご了承ください。

<?php
ini_set('session.save_handler', 'user');

//セッションのオープン時
function sess_open()
{
    return true;
}

//セッションのクローズ時
function sess_close()
{
    return true;
}

//セッションの読み込み時
function sess_read($id)
{
    // セッションの取得(テーブル:sessions)
    // sessions.dataはCLOB型
    $conn = oci_connect("username", "password", "oracle_sid");
    $sql = "SELECT data FROM sessions WHERE sess_id = '$id'";
    $stmt = oci_parse($conn, $sql);
    oci_execute($stmt, OCI_DEFAULT);
    while ( $row = oci_fetch_array($stmt, OCI_ASSOC+OCI_RETURN_LOBS) ){
        $data = $row['DATA'];
    }
    oci_free_statement($stmt);
    oci_close($conn);
    return $data;
}

//セッションの書き込み時
function sess_write($id, $data)
{
    // セッションを一度削除
    $conn = oci_connect("username", "password", "oracle_sid");
    $sql = "DELETE FROM sessions WHERE sess_id = '" . $id . "'";
    $stmt = oci_parse($conn, $sql);
    oci_execute($stmt, OCI_DEFAULT);
    
    // 新たなシーケンスでセッションを再度書き込み
    // シーケンスはOracleトリガーで自動インクリメントされる
    $sql = "INSERT INTO sessions (sess_id, data, update_time) VALUES ('$id', empty_clob(), sysdate) RETURNING data INTO :lob";
    $stmt = oci_parse($conn, $sql);
    $clob = oci_new_descriptor($conn, OCI_D_LOB);
    oci_bind_by_name($stmt, ":lob", &$clob, -1, OCI_B_CLOB);
    oci_execute($stmt, OCI_DEFAULT);
    $clob->save($data);
        
    oci_commit($conn);
    oci_free_statement($stmt);
    oci_close($conn);
    
    $rtn = true;
    return $rtn;
}
 
//セッション破棄時(session_destroy時)
function sess_destroy($id)
{
    // セッションの削除
    $conn = oci_connect("username", "password", "oracle_sid");
    $sql = "DELETE FROM sessions WHERE sess_id = '" . $id . "'";
    $stmt = oci_parse($conn, $sql);
    oci_execute($stmt, OCI_DEFAULT);
    
    oci_commit($conn);
    oci_free_statement($stmt);
    oci_close($conn);
    
    $rtn = true;
    return $rtn;
}

//ガーベージコレクション実行時
function sess_clean($maxlifetime)
{
    // 最終更新日時からmaxlifetime以上経過しているセッションを削除
    $conn = oci_connect("username", "password", "oracle_sid");
    $sql = "DELETE FROM sessions WHERE update_time < ( sysdate - " . $maxlifetime . " / 86400 )";
    $stmt = oci_parse($conn, $sql);
    oci_execute($stmt, OCI_DEFAULT);
    
    oci_commit($conn);
    oci_free_statement($stmt);
    oci_close($conn);
    
    $rtn = true;
    return $rtn;
}

// セッション管理用のユーザー定義のコールバック関数を設定する。
session_set_save_handler('sess_open','sess_close','sess_read','sess_write','sess_destroy','sess_clean');
?>

そういえば・・・

PHPの資格試験が今年(2010年)の秋くらいから始まるらしいですね。
なんでも教科書がオライリー本だとか。