セッション関数
PHP Manual

session_set_save_handler

(PHP 4, PHP 5)

session_set_save_handlerユーザー定義のセッション保存関数を設定する

説明

bool session_set_save_handler ( callable $open , callable $close , callable $read , callable $write , callable $destroy , callable $gc )

PHP 5.4 以降は次のプロトタイプでも登録できます。

bool session_set_save_handler ( SessionHandlerInterface $sessionhandler [, bool $register_shutdown = true ] )

session_set_save_handler() は、セッションに 関連するデータを保存および取得するために使用されるユーザー定義の セッション保存関数を設定します。この関数は、セッションデータを ローカルデータベースに保存する場合のように PHP セッションにより 提供されるもの以外の保存方法を使用したい場合に有用です。

パラメータ

この関数には二種類のプロトタイプがあります。

sessionhandler

SessionHandlerInterface を実装したクラス、たとえば SessionHandler のインスタンスで、 これをセッションハンドラとして登録する。PHP 5.4 以降限定。

register_shutdown

session_write_close()register_shutdown_function() 関数として登録するかどうか。

あるいは
open(string $savePath, string $sessionName)

open コールバックはクラスのコンストラクタのようなもので、セッションを開くときに実行されます。 セッションが自動で開始したり、あるいは手動で session_start() で開始させたりするときに、最初に実行されるコールバック関数がこれです。 成功した場合は TRUE、失敗した場合は FALSE を返します。

close()

close コールバックはクラスのデストラクタのようなもので、write コールバックがコールされた後で実行されます。 また、session_write_close() がコールされたときにも実行されます。 成功した場合は TRUE、失敗した場合は FALSE を返します。

read(string $sessionId)

read コールバックは、常にセッションエンコード (シリアライズ) された文字列を返さなければなりません。何もデータを読み込まなかった場合は空文字列を返します。

このコールバックは、セッションが開始したときや session_start() がコールされたときに PHP が内部的に実行します。 このコールバックを実行する前に、PHP は open コールバックを実行します。

このコールバックが返す値は、 write コールバックがストレージに渡した形式とまったく同じシリアライズ形式でなければなりません。 返された値を PHP が自動的にアンシリアライズして、スーパーグローバル $_SESSION に格納します。データの形式は serialize() したものと似ていますが、実際は違う形式であることに注意しましょう。 シリアライズの方法は ini 設定 session.serialize_handler で指定します。

write(string $sessionId, string $data)

write コールバックは、セッションの保存や終了が必要となったときにコールされます。 このコールバックが受け取るのは、現在のセッション ID とシリアライズ後のスーパーグローバル $_SESSION です。 PHP が内部で利用するシリアライズ方法は、ini 設定 session.serialize_handler で指定します。

このコールバックに渡されたシリアライズ後のセッションデータを、 渡されたセッション ID に対応させて格納しなければなりません。 このデータを取得した read コールバックは、 write コールバックに最初に渡されたのとまったく同じ値を返さなければなりません。

このコールバックが実行されるのは、PHP のスクリプトが終了するときか、あるいは明示的に session_write_close() がコールされたときです。この関数の実行後には、PHP が内部的に close コールバックを実行することに注意しましょう。

注意:

"write" ハンドラは、出力ストリームが閉じてから実行されます。 したがって、"write" ハンドラ内でデバッグ出力を行っても、 それはブラウザに表示されません。 デバッグ出力が必要なら、それをファイルに書き出すようにしましょう。

destroy($sessionId)

このコールバックが実行されるのは、 session_destroy() あるいは session_regenerate_id() (destroy パラメータを TRUE にした場合) を実行し、セッションを破棄した場合です。 成功した場合は TRUE、失敗した場合は FALSE を返します。

gc($lifetime)

ガベージコレクタコールバックは PHP が内部で定期的に実行し、古いセッションデータを破棄します。 実行頻度は session.gc_probability および session.gc_divisor で設定します。 この関数に渡される有効期限の値は session.gc_maxlifetime で設定できます。 成功した場合は TRUE、失敗した場合は FALSE を返します。

返り値

成功した場合に TRUE を、失敗した場合に FALSE を返します。

例1 自作のセッションハンドラ: 完全なコードは SessionHandlerInterface を参照

このコードは、PHP 5.4.0 以降のバージョンで動作します。 ここでは実行するところだけを示します。完全な例は、上でリンクしている SessionHandlerInterface のページを参照ください。

session_set_save_handler() でオブジェクト指向型のプロトタイプを使っていることと、 シャットダウン関数をその parameter フラグで登録していることに注目しましょう。 オブジェクトをセッション保存ハンドラとして使うときには、この方法をおすすめします。

<?php
class MySessionHandler implements SessionHandlerInterface
{
    
// ここでインターフェイスを実装します
}

$handler = new MySessionHandler();
session_set_save_handler($handlertrue);
session_start();

// $_SESSION への値の設定や格納されている値の取得を進めます

例2 セッション保存ハンドラでオブジェクトを使う例

このコードは、PHP 5.4.0 より前のバージョンで動作します。

この例では、ファイルベースのセッションストレージをつくります。これは PHP のデフォルトのセッション保存ハンドラである files と似たものです。この例をさらに拡張すれば、 PHP がサポートするお好みのデータベースを使ってセッションを保存させるようにするのも簡単です。

シャットダウン関数 session_write_close() を、 register_shutdown_function() を使って追加登録していることに注目しましょう。 PHP 5.4.0 より前のバージョンでオブジェクトをセッション保存ハンドラとして使うときには、この方法をおすすめします。

<?php
class FileSessionHandler
{
    private 
$savePath;

    function 
open($savePath$sessionName)
    {
        
$this->savePath $savePath;
        if (!
is_dir($this->savePath)) {
            
mkdir($this->savePath0777);
        }

        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() でセッションを閉じます。

変更履歴

バージョン 説明
5.4.0 SessionHandlerInterface でセッションハンドラを実装したり、 SessionHandler で PHP の内部セッションハンドラを公開したりできるようになりました。

参考


セッション関数
PHP Manual