session_set_save_handler
(PHP 4, PHP 5, PHP 7)
session_set_save_handler — ユーザー定義のセッション保存関数を設定する
説明
session_set_save_handler
( callable $open
, callable $close
, callable $read
, callable $write
, callable $destroy
, callable $gc
[, callable $create_sid
[, callable $validate_sid
[, callable $update_timestamp
]]] ) : bool
PHP 5.4 以降は次のプロトタイプでも登録できます。
session_set_save_handler
( object $sessionhandler
[, bool $register_shutdown
= true
] ) : bool
session_set_save_handler() は、セッションに 関連するデータを保存および取得するために使用されるユーザー定義の セッション保存関数を設定します。この関数は、PHP セッションにより 提供されるもの以外の保存方法を使用したい場合に有用です。 例えば、セッションデータをローカルデータベースに保存します。
パラメータ
この関数には二種類のプロトタイプがあります。
sessionhandler
- SessionHandlerInterface、 SessionIdInterface(オプション) または SessionUpdateTimestampHandlerInterface を実装したクラス、たとえば SessionHandler のインスタンスで、 これをセッションハンドラとして登録する。PHP 5.4 以降限定。
register_shutdown
- session_write_close() を register_shutdown_function() 関数として登録するかどうか。
あるいは
open
以下のシグナチャを持つ callable:
open ( string
$savePath
, string$sessionName
) : boolopen コールバックはクラスのコンストラクタのようなもので、セッションを開くときに実行されます。 セッションが自動で開始したり、あるいは手動で session_start() で開始させたりするときに、最初に実行されるコールバック関数がこれです。 成功した場合は
true
、失敗した場合はfalse
を返します。close
以下のシグナチャを持つ callable:
close ( ) : bool
close コールバックはクラスのデストラクタのようなもので、write コールバックがコールされた後で実行されます。 また、session_write_close() がコールされたときにも実行されます。 成功した場合は
true
、失敗した場合はfalse
を返します。read
以下のシグナチャを持つ callable:
read ( string
$sessionId
) : stringread
コールバックは、常にセッションエンコード (シリアライズ) された文字列を返さなければなりません。何もデータを読み込まなかった場合は空文字列を返します。このコールバックは、セッションが開始したときや session_start() がコールされたときに PHP が内部的に実行します。 このコールバックを実行する前に、PHP は
open
コールバックを実行します。このコールバックが返す値は、
write
コールバックがストレージに渡した形式とまったく同じシリアライズ形式でなければなりません。 返された値を PHP が自動的にアンシリアライズして、スーパーグローバル$_SESSION
に格納します。データの形式は serialize() したものと似ていますが、実際は違う形式であることに注意しましょう。 シリアライズの方法は ini 設定 session.serialize_handler で指定します。write
以下のシグナチャを持つ callable:
write ( string
$sessionId
, string$data
) : boolwrite
コールバックは、セッションの保存や終了が必要となったときにコールされます。 このコールバックが受け取るのは、現在のセッション ID とシリアライズ後のスーパーグローバル$_SESSION
です。 PHP が内部で利用するシリアライズ方法は、ini 設定 session.serialize_handler で指定します。このコールバックに渡されたシリアライズ後のセッションデータを、 渡されたセッション ID に対応させて格納しなければなりません。 このデータを取得した
read
コールバックは、write
コールバックに最初に渡されたのとまったく同じ値を返さなければなりません。このコールバックが実行されるのは、PHP のスクリプトが終了するときか、あるいは明示的に session_write_close() がコールされたときです。この関数の実行後には、PHP が内部的に
close
コールバックを実行することに注意しましょう。注意:
"write" ハンドラは、出力ストリームが閉じてから実行されます。 したがって、"write" ハンドラ内でデバッグ出力を行っても、 それはブラウザに表示されません。 デバッグ出力が必要なら、それをファイルに書き出すようにしましょう。
destroy
以下のシグナチャを持つ callable:
destroy ( string
$sessionId
) : boolこのコールバックが実行されるのは、 session_destroy() あるいは session_regenerate_id() (destroy パラメータを
true
にした場合) を実行し、セッションを破棄した場合です。 成功した場合はtrue
、失敗した場合はfalse
を返します。gc
以下のシグナチャを持つ callable:
gc ( int
$lifetime
) : boolガベージコレクタコールバックは PHP が内部で定期的に実行し、古いセッションデータを破棄します。 実行頻度は session.gc_probability および session.gc_divisor で設定します。 この関数に渡される有効期限の値は session.gc_maxlifetime で設定できます。 成功した場合は
true
、失敗した場合はfalse
を返します。create_sid
以下のシグナチャを持つ callable:
create_sid ( ) : string
このコールバックは、新しいセッション ID が必要になったときに実行されます。 パラメータは不要です。返り値は、使っているハンドラで有効なセッション ID を表す文字列となります。
validate_sid
以下のシグナチャを持つ callable:
validate_sid ( string
$key
) : boolこのコールバックは、セッションが開始された場合に実行されます。 但し、セッションID が渡され、 session.use_strict_mode が有効な場合に限ります。
key
は検証する セッションID を指定します。 渡されたID のセッションが既に存在する場合、セッションID は有効です。 成功した場合はtrue
、失敗した場合はfalse
を返します。update_timestamp
以下のシグナチャを持つ callable:
update_timestamp ( string
$key
, string$val
) : boolこのコールバックは、セッションが更新された時に実行されます。
key
はセッションID、val
はセッションデータを指定します。 成功した場合はtrue
、失敗した場合はfalse
を返します。
返り値
成功した場合に true
を、失敗した場合に false
を返します。
例
例1 自作のセッションハンドラ: 完全なコードは SessionHandlerInterface を参照
このコードは、PHP 5.4.0 以降のバージョンで動作します。 ここでは実行するところだけを示します。完全な例は、上でリンクしている SessionHandlerInterface のページを参照ください。
session_set_save_handler() でオブジェクト指向型のプロトタイプを使っていることと、 シャットダウン関数をその parameter フラグで登録していることに注目しましょう。 オブジェクトをセッション保存ハンドラとして使うときには、この方法をおすすめします。
<?phpclass MySessionHandler implements SessionHandlerInterface{ // ここでインターフェイスを実装します}$handler = new MySessionHandler();session_set_save_handler($handler, true);session_start();// $_SESSION への値の設定や格納されている値の取得を進めます
例2 セッション保存ハンドラでオブジェクトを使う例
このコードは、PHP 5.4.0 より前のバージョンで動作します。
この例では、ファイルベースのセッションストレージをつくります。これは
PHP のデフォルトのセッション保存ハンドラである files
と似たものです。この例をさらに拡張すれば、
PHP がサポートするお好みのデータベースを使ってセッションを保存させるようにするのも簡単です。
シャットダウン関数 session_write_close() を、 register_shutdown_function() を使って追加登録していることに注目しましょう。 PHP 5.4.0 より前のバージョンでオブジェクトをセッション保存ハンドラとして使うときには、この方法をおすすめします。
<?phpclass FileSessionHandler{ private $savePath; function open($savePath, $sessionName) { $this->savePath = $savePath; if (!is_dir($this->savePath)) { mkdir($this->savePath, 0777); } return true; } function close() { return true; } function read($id) { return (string)@file_get_contents("$this->savePath/sess_$id"); } function write($id, $data) { return file_put_contents("$this->savePath/sess_$id", $data) === false ? false : true; } function destroy($id) { $file = "$this->savePath/sess_$id"; if (file_exists($file)) { unlink($file); } return true; } function gc($maxlifetime) { foreach (glob("$this->savePath/sess_*") as $file) { if (filemtime($file) + $maxlifetime < time() && file_exists($file)) { unlink($file); } } return true; }}$handler = new FileSessionHandler();session_set_save_handler( array($handler, 'open'), array($handler, 'close'), array($handler, 'read'), array($handler, 'write'), array($handler, 'destroy'), array($handler, 'gc') );// これは、オブジェクトを保存ハンドラとして使ったときの予期せぬ副作用を防ぎますregister_shutdown_function('session_write_close');session_start();// $_SESSION への値の設定や格納されている値の取得を進めます
注意
警告
オブジェクトをセッション保存ハンドラとして使うときには、
シャットダウン関数を PHP に登録しておくことが重要です。
これで、PHP スクリプトの終了時に内部的にオブジェクトを破棄する処理による副作用や、
write
および close
がコールされてしまうことを防げます。
一般的には、'session_write_close'
を
register_shutdown_function() 関数で登録しなければなりません。
PHP 5.4.0 以降では session_register_shutdown() を使えます。あるいは session_set_save_handler() をオブジェクト指向のメソッドとして実行するときに 'register shutdown' フラグを使い、SessionHandlerInterface を実装したインスタンスを渡すという方法もあります。
警告
PHP 5.0.5 以降、write
ハンドラおよび
close
ハンドラはオブジェクトが破棄されたあとにコールされます。
そのため、これらのハンドラでオブジェクトを使ったり例外をスローしたりすることはできません。
例外をキャッチできないのでその情報をトレースすることもできず、
例外は単純に無視されてしまいます。
しかし、オブジェクトのデストラクタではセッションを使えます。
この「ニワトリが先かタマゴが先か」の問題を解決するために、 デストラクタから session_write_close() をコールできますが、より確実なのは先述のとおりシャットダウン関数を登録することです。
警告 SAPI の種類によっては、スクリプトの終了時にセッションを閉じると 現在の作業ディレクトリが変わってしまうことがあります。これを防ぐには、 事前に session_write_close() でセッションを閉じます。
参考
- 設定ディレクティブ session.save_handler
- 設定ディレクティブ session.serialize_handler
- register_shutdown_function() - シャットダウン時に実行する関数を登録する
- session_register_shutdown() - セッションのシャットダウン関数 (PHP 5.4.0 以降)
- 手続き型の完全なリファレンス実装は » save_handler.inc を参照してください。