gallu’s blog

エンジニアでゲーマーで講師で占い師なおいちゃんのブログです。

セッション関連、作ろうかなぁ?

もっそ雑に調べたのですが。

<?php

$_SESSION = array();
$session = array();

function hoge() {
  $_SESSION['test'] = 999;
  $session['test'] = 999;
}

hoge();
var_dump($_SESSION);
var_dump($session);

が、まぁ予想通り

$ php ttt.php
array(1) {
["test"]=>
int(999)
}
array(0) {
}

となって、なにかってぇとつまり「$_SESSIONは別にsession_start()しなくても普通にスーパーグローバル変数として使えるぽい」ので。


そうすると…いくつか、PHPのセッションで気になる事もあって(…まぁ、PHPC言語ソースコードを一番初めに読んだ理由もそこだったしなぁ)。
特に一番気になるのが「セッションIDが存在しなかったら新しくつくる」あたり。
これは「session_start()時に何も情報がなかったら新しく自動で作る」も「session_start()時にCookieからID渡されたんだけどこっちには情報がない時に自動で作る」も、どっちの意味も含めて。
もちろん「anonymouseなセッションが欲しい」場合もあるんだけど、一方で「純粋にログイン認証者にのみ発行したいセッション」もあるので。


なんか別に「PHPのセッションのままでもいい」ような気もしているのですが、なんとなく思考が走ったので、いったん、備忘録的にクラスの作りを記述しておこうかなぁ、っと。
ニーズが多かったら作りますw

// 初期設定系:set系は「start()」call以降は例外でも吐きましょうかねぇ
mw_session::set_name($name); // session_name()で引数与えたのと同じ挙動
mw_session::get_name(); //  session_name()と同じ挙動
// XXX以下面倒なんでsetterとgetter混雑で記述
mw_session::[sg]et_expire(int); // セッション寿命。寿命が来たら基本的には「問答無用で殺す」。引数は分単位?
mw_session::[sg]et_session_data_rw_class_name(string); // セッション情報を読み書きする、いわゆる「SessionHandlerInterfaceクラス」のクラス名:Interfaceで縛る:デフォはRDBかしら?
// Cookie関連
mw_session::[sg]et_cookie_lifetime(int); // Cookieの寿命:デフォは0かねぇ?
mw_session::[sg]et_cookie_path(string); // Cookieで設定するpath:デフォは / かねぇ?
mw_session::cookie_secure_on(); // Cookieのセキュア属性を有効にする
mw_session::cookie_secure_off(); // Cookieのセキュア属性を無効にする:デフォは、まださすがにこっちかねぇ?
mw_session::is_cookie_secure(); // Cookieのセキュア属性を確認
mw_session::cookie_httponly_on(); // httponly属性をonに試みる:デフォこっちで
mw_session::cookie_httponly_off(); // httponly属性をoffに試みる:…このメソッドいるか? そもそも
mw_session::is_cookie_httponly(); // httponly属性を確認
// 特殊
mw_session::injection_expire_logic(object); // セッションの寿命判定を「特殊なものにしたい場合」用のロジック注入口。Interfaceで縛る?
mw_session::injection_create_session_id_logic(object); // セッションIDの作成方法を「特殊なものにしたい場合」用のロジック注入口。Interfaceで縛る? デフォはDIIDかしら?
mw_session::injection_serializer_logic(object); // セッションデータのシリアライズ方法を「特殊なものにしたい場合」用のロジック注入口。Interfaceで縛る? デフォはPHPの普通のserializeになると思う

// ----------------------------------------
// セッションのstart。「セッションテーブルにIDが存在しない」場合、falseが帰ってくる&新規セッションは作らない
mw_session::start();
  // XXX register_shutdown_function()関数つかって、mw_session::end()関数をcallできるようにしておく。end()で、セッションを書き込む
  // 引数で明示的にtrueを指定したら「anonymouseなセッションを許容する(存在しないIDなら作る)」とか、やっとくか? いらないか?

// XXX データはそのまま$_SESSIONに書き込む

// 終了時はシャットダウン関数経由で書き込みが行われる

-------------------
// セッションIDの張り替え。session_regenerate_id(true)と同じように動かす
mw_session::regenerate_id();

-------------------
// セッションの作成。「ログイン成功時」とかこれだよねぇ多分
mw_session::create();

-------------------
// セッションの破棄。セッションIDを亡き者にする。ついでにdataも壊すよねぇふつう。
mw_session::create();


あとはいわゆる「SessionHandlerInterfaceクラス」相当のやつのインタフェースだなぁ。
多分、こんな感じ。

abstract class session_data_rw {
  // セッションIDの設定
  public function set_id($id) { $this->id_ = $id; }

  // セッション開始時
  abstract public function read();

  // セッション終了時
  abstract public function write();

  // セッション削除時
  abstract public function delete();

  // セッション作成時
  abstract public function create();

//private:
private $id_;
}


ここを起点にして。
「ファイルベース」の場合、多分メソッドに「set_save_path(string)」とかいうメソッドが追加されて。
RDBベース」の場合、多分メソッドに「[sg]et_dbh($dbh)」と、「[sg]et_session_clump_name(string)」が追加されて。


ふむ…イメージはわりとがっちょり固まったなぁw
あとは作る気力なんだけど……まぁ「ログイン時のみ有効なセッション ≒ サーバ側が作ってないセッションIDを頑なに受け入れない」というセッション機構は実際欲しいシーンはあったりするので。
なんとなく、そのうち上の実装、やってるような気がするなぁ…実装のイメージつくしなぁ実装そのものは多分1〜2時間とか、テスト入れても、簡易なテストくらいなら半日かからんだろうし。


軽く賛否伺いたかったりするので、ご意見がありましたら、ぜひ。
「はよ作れ」も歓迎いたしまするw


追記
register_shutdown_function()関数微妙に不安が走った…。
まぁ基本的には「MagicWeaponで使う」想定なので、Weaponのcontrollerのfin処理…か、そうかmodelのfin処理でend()叩いてもいいんだな。二重callはmodel側でも禁則処理書けるし、end()ん中でも書いてもいいし。
どのみち「Viewでセッション変数いじる」とか死んでもやらせる気ねぇしw