PHP: セッション情報をデータベースに保存する

1. このページの目的

PHPのセッション情報をデータベースに保存してみる。

本ページでは、SQLite を使用する。

2. やり方

  1. セッション情報を管理するテーブルを作成する。
  2. セッションハンドラクラスを定義する。この中で、データベースにアクセスする処理を記述する。
  3. session_set_save_handler()関数で、セッションハンドラクラスのインスタンスを指定する。
  4. session_start()関数で、セッションを開始する。

3. コード

(1) セッション情報を管理する SQLite のテーブル構造

CREATE TABLE php_sessions (
  session_id TEXT PRIMARY KEY,
  session_updated INTEGER NOT NULL,
  session_data TEXT
);

(2) MySessionHandler.php

<?php
class MySessionHandler implements SessionHandlerInterface {

  private $db;

  function __construct($db_file) {
    $this->db = new SQLite3($db_file);
  }

  public function open($save_path, $name) {
    return true;
  }

  public function read($session_id) {
    $session_data = '';
    $stmt = $this->db->prepare("SELECT session_data FROM php_sessions WHERE session_id=:id");
    if ($stmt) {
      $stmt->bindParam(":id", $session_id);
      $res = $stmt->execute();
      if ($res->numColumns()) {
        $row = $res->fetchArray(SQLITE3_ASSOC);
        if ($row !== false) {
          $session_data = $row['session_data'];
        }
      }
    }
    return $session_data;
  }

  public function write($session_id, $session_data) {
    $affected_rows = 0;
    date_default_timezone_set("UTC");
    $session_updated = time();
    $stmt = $this->db->prepare(
      "REPLACE INTO php_sessions (session_id, session_updated, session_data)
       VALUES(:id, :updated, :data)");
    if($stmt){
      $stmt->bindParam(':id', $session_id);
      $stmt->bindParam(':updated', $session_updated);
      $stmt->bindParam(':data', $session_data);
      $stmt->execute();
    }

    return true;
  }

  public function destroy($session_id) {
    $stmt = $this->db->prepare("DELETE FROM php_sessions WHERE session_id = :id");
    if ($stmt) {
      $stmt->bindParam(":id", $session_id);
      $stmt->execute();
    }
    return true;
  }

  public function close() {
    return true;
  }

  public function gc($maxlifetime) {
    $stmt = $this->db->prepare("DELETE FROM php_sessions WHERE session_updated < :updated");
    if ($stmt) {
      date_default_timezone_set("UTC");
      $t = time() - $maxlifetime;
      $stmt->bindParam(":updated", $t);
      $stmt->execute();
    }
    return true;
  }
}

(3) このページ内のPHPコード抜粋

// セッションハンドラを設定する
require_once('./MySessionHandler.php');
$sess_handler = new MySessionHandler('./db.db');
session_set_save_handler($sess_handler, true);

// セッションを開始する
session_start([
  'cookie_secure' => true,
  'cookie_httponly' => true,
  'cookie_samesite' => 'lax',
]);

$_SESSION['name'] = 'foo';
$_SESSION['age'] = 100;

4. 値を表示する

(1) session_id() の出力

9a2600fc8697bcc4c0cba4855b71a998

(2) セッションクッキーの名前

PHPSESSID

(3) セッションのデータ

array(2) { ["name"]=> string(3) "foo" ["age"]=> int(100) }

5. メモ

6. 参考