エントリー

PHPでセッションハンドラを自作

PHPは標準機能でセッション管理ができますが、何故かセッション管理のみが正しく動作しないサーバーがあったので、セッションハンドラで対応してみた。

PHPでは標準命令の session_set_save_handler() を使用すれば、セッションを扱う際の挙動を自分で決めることができます。(セッションをMySQLで管理する仕組みを自作したり、など。)

以下はファイルでセッションを管理するサンプル。

<?php

define('SESSION_HANDLER_PATH', dirname(__FILE__) . '/sessions/');
define('SESSION_HANDLER_PREFIX', 'session_');
define('SESSION_HANDLER_EXTENSION', '.log');

if (SESSION_HANDLER_PATH != '') {
  $session_handler_path = SESSION_HANDLER_PATH;
} else {
  $session_handler_path = '';
}

function session_handler_open($save_path, $session_name) {
  global $session_handler_path;

  if ($session_handler_path == '') {
    $session_handler_path = $save_path;
  }

  return true;
}

function session_handler_close() {
  global $session_handler_path;

  return true;
}

function session_handler_read($session_id) {
  global $session_handler_path;

  $file = $session_handler_path . SESSION_HANDLER_PREFIX . $session_id . SESSION_HANDLER_EXTENSION;

  if (file_exists($file)) {
    return file_get_contents($file);
  } else {
    return null;
  }
}

function session_handler_write($session_id, $data) {
  global $session_handler_path;

  $file = $session_handler_path . SESSION_HANDLER_PREFIX . $session_id . SESSION_HANDLER_EXTENSION;

  return file_put_contents($file, $data);
}

function session_handler_destroy($session_id) {
  global $session_handler_path;

  $file = $session_handler_path . SESSION_HANDLER_PREFIX . $session_id . SESSION_HANDLER_EXTENSION;

  unlink($file);

  return true;
}

function session_handler_gc($lifetime) {
  global $session_handler_path;

  if ($dir = scandir($session_handler_path)) {
    foreach ($dir as $entry) {
      if (is_file($session_handler_path . $entry) and preg_match('/^' . preg_quote(SESSION_HANDLER_PREFIX, '/') . '\w+' . preg_quote(SESSION_HANDLER_EXTENSION, '/') . '$/i', $entry) and time() - filemtime($session_handler_path . $entry) > $lifetime) {
        unlink($session_handler_path . $entry);
      }
    }
  }

  return true;
}

session_set_save_handler(
  'session_handler_open',
  'session_handler_close',
  'session_handler_read',
  'session_handler_write',
  'session_handler_destroy',
  'session_handler_gc'
);

?>

上のコードを一例ですが session_handler.php という名前で保存し、同じディレクトリ内に sessions というディレクトリを作成します。この中にセッションの情報が保存されます。

session_set_save_handler() 関数によって、「セッションを開始した時は session_handler_open() が呼ばれる」「セッションを保存する時は session_handler_write() が呼ばれる」のような設定を行っています。

以降は、以下のコードで自作のセッション管理を利用できます。

<?php

include_once('session_handler.php');
session_start();

if (isset($_SESSION['count'])) {
  $_SESSION['count']++;
} else {
  $_SESSION['count'] = 1;
}

?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>サンプル</title>
</head>
<body>
<?php

echo $_SESSION['count'] . '回目のアクセスです。';

?>
</body>
</html>

include_once('session_handler.php'); でファイルを読み込む以外は、ごく普通のセッション利用サンプルです。

急きょ書いたコードなので変な箇所があるかもしれません。また、名前の重複を避けるためにもクラス化した方が良かったかも。と思っていたら、公式サイトにクラスのサンプルがあった…。またそのうち調べる予定。

ページ移動

ユーティリティ

カテゴリー

検索

エントリー検索フォーム
キーワード

過去ログ

過去ログ表示フォーム
キーワード

Feed