【PHP8.x】SessionHandlerInterface::write()メソッドの使い方
writeメソッドの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
writeメソッドは、現在のセッションIDに関連付けられたセッションデータを、指定されたストレージに書き込み、永続化するメソッドです。このメソッドは、PHPの標準セッションハンドラではなく、開発者が独自のセッション管理機構を実装するためのSessionHandlerInterfaceインターフェースの一部として定義されます。
PHPのセッション処理において、セッションデータが変更され、その変更を永続的に保存する必要がある場合に、PHPエンジンによって内部的に呼び出されます。具体的には、スクリプトの実行終了時、またはsession_write_close()関数が明示的に呼び出された際に実行されます。
writeメソッドは二つの引数を取ります。一つ目は現在のセッションを一意に識別する文字列である$session_id、二つ目は保存すべきセッションデータを文字列として格納した$session_dataです。このメソッドの実装では、受け取った$session_idに対応する$session_dataを、データベースやファイルシステム、キャッシュシステムなど、開発者が指定した永続的なストレージに安全に保存する処理を記述します。
処理が正常に完了し、セッションデータがストレージに書き込まれた場合はtrueを、何らかの問題が発生して書き込みに失敗した場合はfalseを返します。この戻り値は、PHPエンジンがセッションの保存が成功したかどうかを判断するために使用されるため、正確な値を返すことが重要です。カスタムセッションハンドラを実装する上で、セッションデータの整合性と永続性を保証するために非常に重要な役割を担います。
構文(syntax)
1<?php 2 3class CustomSessionHandler implements SessionHandlerInterface 4{ 5 public function write(string $session_id, string $session_data): bool 6 { 7 // ここにセッションデータ ($session_data) をセッションID ($session_id) に関連付けて永続化する処理を記述します。 8 // 成功した場合は true、失敗した場合は false を返します。 9 return true; 10 } 11 12 // 他の SessionHandlerInterface メソッドも実装する必要がありますが、 13 // ここでは write メソッドの構文例に焦点を当てています。 14 public function open(string $path, string $name): bool { return true; } 15 public function close(): bool { return true; } 16 public function read(string $session_id): string|false { return ''; } 17 public function destroy(string $session_id): bool { return true; } 18 public function gc(int $max_lifetime): int|false { return 0; } 19 public function create_sid(): string { return ''; } 20 public function validate_sid(string $session_id): bool { return true; } 21 public function update_timestamp(string $session_id, string $session_data): bool { return true; } 22}
引数(parameters)
string $id, string $data
- string $id: セッションIDを指定する文字列
- string $data: セッションに保存するデータを指定する文字列
戻り値(return)
bool
セッションデータの保存に成功した場合は true、失敗した場合は false を返します。
サンプルコード
PHP セッションデータをファイルに書き込む
1<?php 2 3/** 4 * FileSessionHandler クラスは、PHPのSessionHandlerInterfaceを実装し、 5 * セッションデータをファイルシステムに保存・管理します。 6 * システムエンジニアを目指す初心者の方にも理解しやすいよう、セッションの仕組みを 7 * 具体的にファイル操作と紐づけて示します。 8 */ 9class FileSessionHandler implements SessionHandlerInterface 10{ 11 private string $savePath; 12 13 /** 14 * コンストラクタ。セッションファイルを保存するディレクトリを設定します。 15 * ディレクトリが存在しない場合は作成します。 16 */ 17 public function __construct(string $savePath) 18 { 19 if (!is_dir($savePath)) { 20 mkdir($savePath, 0777, true); 21 } 22 $this->savePath = $savePath; 23 } 24 25 /** 26 * セッションIDに基づいて、セッションファイルの完全なパスを生成します。 27 */ 28 private function getFilePath(string $id): string 29 { 30 return $this->savePath . '/sess_' . $id; 31 } 32 33 /** 34 * セッションを開きます。ファイルベースのセッションでは、特別なリソースを開く必要はありません。 35 * 36 * @param string $path セッションの保存パス (通常は無視されます)。 37 * @param string $name セッションの名前 (通常は無視されます)。 38 * @return bool 常にtrueを返します。 39 */ 40 public function open(string $path, string $name): bool 41 { 42 return true; 43 } 44 45 /** 46 * セッションを閉じます。ファイルベースのセッションでは、特別なリソースを閉じる必要はありません。 47 * 48 * @return bool 常にtrueを返します。 49 */ 50 public function close(): bool 51 { 52 return true; 53 } 54 55 /** 56 * 指定されたセッションIDに対応するセッションデータをファイルから読み込みます。 57 * ファイルが存在しない場合は空の文字列を返します。 58 * 59 * @param string $id 読み込むセッションのID。 60 * @return string 読み込んだセッションデータ、または空の文字列。 61 */ 62 public function read(string $id): string 63 { 64 $filePath = $this->getFilePath($id); 65 if (file_exists($filePath)) { 66 return (string)file_get_contents($filePath); 67 } 68 return ''; 69 } 70 71 /** 72 * 指定されたセッションIDとデータをファイルに書き込みます。 73 * このメソッドは、PHPのセッション処理において、$_SESSIONに格納されたデータを永続化する際に呼ばれます。 74 * 「php write to file」のキーワードに最も関連性の高い部分です。 75 * 76 * @param string $id 書き込むセッションのID。 77 * @param string $data シリアライズされたセッションデータ。 78 * @return bool 書き込みが成功した場合はtrue、失敗した場合はfalse。 79 */ 80 public function write(string $id, string $data): bool 81 { 82 $filePath = $this->getFilePath($id); 83 // file_put_contents関数で、指定されたファイルにデータを書き込みます。 84 // ファイルが存在しない場合は作成され、存在する場合は上書きされます。 85 return file_put_contents($filePath, $data) !== false; 86 } 87 88 /** 89 * 指定されたセッションIDに対応するセッションファイルを削除して、セッションを破棄します。 90 * 91 * @param string $id 破棄するセッションのID。 92 * @return bool 破棄が成功した場合はtrue、ファイルが存在しなかった場合もtrueを返します。 93 */ 94 public function destroy(string $id): bool 95 { 96 $filePath = $this->getFilePath($id); 97 if (file_exists($filePath)) { 98 return unlink($filePath); // ファイルを削除します。 99 } 100 return true; 101 } 102 103 /** 104 * ガベージコレクション (GC) を実行し、期限切れのセッションファイルを削除します。 105 * 106 * @param int $max_lifetime セッションの最大有効期間(秒)。 107 * @return int 削除されたセッションファイルの数。 108 */ 109 public function gc(int $max_lifetime): int 110 { 111 $count = 0; 112 // すべてのセッションファイル('sess_'で始まるファイル)を検索します。 113 foreach (glob($this->savePath . '/sess_*') as $file) { 114 // ファイルが存在し、最終更新時刻から最大有効期間を超えている場合 115 if (file_exists($file) && filemtime($file) + $max_lifetime < time()) { 116 unlink($file); // ファイルを削除します。 117 $count++; 118 } 119 } 120 return $count; 121 } 122} 123 124// --- このカスタムセッションハンドラの利用例 --- 125 126// セッションファイルを保存するためのディレクトリを指定します。 127// このスクリプトが実行される場所と同じディレクトリに 'sessions' フォルダが作成されます。 128$sessionSavePath = __DIR__ . '/sessions'; 129 130// FileSessionHandlerのインスタンスを作成します。 131$handler = new FileSessionHandler($sessionSavePath); 132 133// PHPに、標準のセッションハンドラではなく、このカスタムハンドラを使うように登録します。 134// 第二引数の 'true' は、PHPのデフォルトのセッション保存ハンドラを置き換えることを意味します。 135session_set_save_handler($handler, true); 136 137// セッションを開始します。 138// これにより、PHPは必要に応じて FileSessionHandler の read() メソッドを呼び出し、 139// 既存のセッションデータを読み込もうとします。 140session_start(); 141 142// セッションにデータを設定します。 143// このデータは、スクリプトの終了時、または session_write_close() が呼ばれたときに、 144// FileSessionHandler の write() メソッドを通じてファイルに保存されます。 145$_SESSION['user_id'] = 123; 146$_SESSION['username'] = 'beginner_se'; 147$_SESSION['login_time'] = time(); 148 149// セッションの終了処理を行い、$_SESSIONに格納されたデータが 150// FileSessionHandler::write() メソッドを使ってファイルに書き込まれることを保証します。 151session_write_close(); 152 153// このスクリプトを実行すると、指定された `$sessionSavePath` ディレクトリ内に 154// 'sess_' で始まるセッションファイルが作成され、上記で設定された $_SESSION の内容が保存されます。
PHPのSessionHandlerInterface::writeメソッドは、カスタムセッションハンドラにおいて、セッションデータを永続的なストレージ(このサンプルコードではファイルシステム)に書き込む際に呼び出される重要なメソッドです。PHPの標準的なセッション処理では、$_SESSIONスーパーグローバル変数に格納されたデータは、スクリプトの終了時やsession_write_close()関数が呼び出された際に、このwriteメソッドを通じて自動的に保存されます。
サンプルコードのFileSessionHandlerクラスにおけるwriteメソッドは、このインターフェースを実装し、セッションデータを具体的にファイルへ書き込む処理を担っています。このメソッドはstring $idとstring $dataの2つの引数を受け取ります。$idはセッションを一意に識別するための文字列で、保存するセッションファイルの名前の一部として使用されます。$dataは、$_SESSIONに格納されていた情報がPHPによってシリアライズ(文字列化)されたもので、ファイルに書き込まれる実際のセッション内容となります。
メソッド内部では、まずgetFilePath()メソッドを使用して$idから完全なファイルパスを生成します。その後、PHPのfile_put_contents()関数を用いて、指定されたファイルパスに$dataの内容を書き込みます。この関数は、ファイルが存在しない場合は新しく作成し、既に存在する場合はその内容を上書きします。メソッドの戻り値はbool型で、データの書き込みが成功した場合はtrue、何らかの理由で失敗した場合はfalseを返します。このwriteメソッドにより、ユーザーのセッションデータが永続化され、異なるリクエスト間でもセッション状態が維持されます。
writeメソッドは、$_SESSIONに格納されたデータがファイルに永続化される際に、PHPによって自動的に呼び出されます。この機能が「php write to file」の核心部分です。
最も重要な注意点は、セッションファイルを保存するディレクトリ($savePath)に、PHP実行ユーザーが書き込み権限を持つことです。権限がないと、セッションデータは正しく保存されません。
また、セッションIDからファイルパスを生成する際には、セキュリティリスク(例: パスインジェクション)を考慮し、ファイル名の安全性を確保してください。より堅牢なシステムでは、複数のリクエストが同時にセッションファイルに書き込む際のデータ破損を防ぐため、排他ロック(例: file_put_contents関数のLOCK_EXフラグ)の利用も検討しましょう。メソッドがtrueを返せば書き込み成功、falseを返せば失敗とPHPに通知されます。
PHPでセッションをテキストファイルに保存する
1<?php 2 3/** 4 * カスタムセッションハンドラを実装するクラス。 5 * SessionHandlerInterface を実装することで、PHPの標準セッション管理を独自の方法で上書きできます。 6 * この例では、セッションデータをテキストファイルに保存します。 7 */ 8class FileSessionHandler implements SessionHandlerInterface 9{ 10 private string $savePath; 11 12 /** 13 * コンストラクタ。セッションファイルを保存するディレクトリパスを受け取ります。 14 * 15 * @param string $savePath セッションファイルを保存するディレクトリのパス 16 */ 17 public function __construct(string $savePath) 18 { 19 $this->savePath = $savePath; 20 // 保存ディレクトリが存在しない場合は作成します 21 if (!is_dir($this->savePath)) { 22 mkdir($this->savePath, 0777, true); 23 } 24 } 25 26 /** 27 * セッションを開きます。 28 * このメソッドは session_start() の際に最初に呼び出されます。 29 * 30 * @param string $path セッションの保存パス (通常は php.ini の session.save_path の値) 31 * @param string $name セッション名 (通常は php.ini の session.name の値) 32 * @return bool 成功した場合は true、失敗した場合は false 33 */ 34 public function open(string $path, string $name): bool 35 { 36 // 特にリソースを開く必要がなければ、trueを返します 37 return true; 38 } 39 40 /** 41 * セッションを閉じます。 42 * このメソッドはスクリプト終了時や session_write_close() が呼び出されたときに呼び出されます。 43 * 44 * @return bool 成功した場合は true、失敗した場合は false 45 */ 46 public function close(): bool 47 { 48 // 特にクローズするリソースがなければ、trueを返します 49 return true; 50 } 51 52 /** 53 * セッションデータを読み込みます。 54 * このメソッドは session_start() の際に呼び出され、指定されたセッションIDのデータを取得します。 55 * 56 * @param string $id 読み込むセッションのID 57 * @return string セッションデータ (文字列) またはデータがない場合は空文字列 58 */ 59 public function read(string $id): string 60 { 61 $sessionFile = $this->savePath . '/' . $id . '.sess'; 62 if (file_exists($sessionFile)) { 63 // ファイルからセッションデータを読み込みます 64 return file_get_contents($sessionFile); 65 } 66 return ''; // データがない場合は空文字列を返します 67 } 68 69 /** 70 * セッションデータを書き込みます。 71 * このメソッドは、セッションデータが変更された際や session_write_close() が呼び出されたときに実行されます。 72 * ここでセッションID ($id) とセッションデータ ($data) をテキストファイルに保存します。 73 * 74 * @param string $id 書き込むセッションのID 75 * @param string $data 書き込むセッションデータ 76 * @return bool 成功した場合は true、失敗した場合は false 77 */ 78 public function write(string $id, string $data): bool 79 { 80 $sessionFile = $this->savePath . '/' . $id . '.sess'; 81 // セッションデータをテキストファイルに書き込みます。 82 // LOCK_EX は、同時に複数のプロセスがファイルに書き込もうとするのを防ぐための排他ロックです。 83 return file_put_contents($sessionFile, $data, LOCK_EX) !== false; 84 } 85 86 /** 87 * セッションを破棄します。 88 * session_destroy() が呼び出されたときに実行され、指定されたセッションIDのデータを削除します。 89 * 90 * @param string $id 破棄するセッションのID 91 * @return bool 成功した場合は true、失敗した場合は false 92 */ 93 public function destroy(string $id): bool 94 { 95 $sessionFile = $this->savePath . '/' . $id . '.sess'; 96 if (file_exists($sessionFile)) { 97 // セッションファイルを削除します 98 return unlink($sessionFile); 99 } 100 return true; // ファイルが存在しない場合も成功とみなします 101 } 102 103 /** 104 * ガベージコレクション (GC) を実行します。 105 * 古いセッションデータを削除するために、PHPによって定期的に呼び出されます。 106 * 107 * @param int $max_lifetime セッションの最大有効期間 (秒) 108 * @return int 削除されたセッションファイルの数 109 */ 110 public function gc(int $max_lifetime): int 111 { 112 $deletedCount = 0; 113 // 指定されたパス内の全てのセッションファイルを探します 114 foreach (glob($this->savePath . '/*.sess') as $file) { 115 // ファイルの最終更新時刻が最大有効期間よりも古い場合 116 if (filemtime($file) + $max_lifetime < time() && file_exists($file)) { 117 unlink($file); // ファイルを削除します 118 $deletedCount++; 119 } 120 } 121 return $deletedCount; 122 } 123} 124 125// --- サンプルコードの実行部分 --- 126 127// セッションファイルを保存するディレクトリを指定します。 128// スクリプトと同じディレクトリに 'sessions' フォルダが作成されます。 129$sessionSavePath = __DIR__ . '/sessions'; 130 131// カスタムセッションハンドラのインスタンスを作成します。 132$handler = new FileSessionHandler($sessionSavePath); 133 134// PHPにカスタムセッションハンドラを使用するように登録します。 135// true は、登録後にグローバルな $_SESSION 変数を初期化することを意味します。 136session_set_save_handler($handler, true); 137 138// セッションを開始します。 139// これにより、open() メソッドが呼び出され、read() メソッドで既存のセッションデータが読み込まれます。 140session_start(); 141 142// セッションにデータを設定します。 143$_SESSION['user_id'] = 123; 144$_SESSION['username'] = 'beginner_se'; 145$_SESSION['message'] = 'Hello from custom session handler!'; 146 147echo "セッションデータを設定しました。\n"; 148echo "現在のセッションID: " . session_id() . "\n"; 149echo "データは '{$sessionSavePath}/" . session_id() . ".sess' に保存されます。\n"; 150 151// セッションを終了し、データを保存します。 152// これにより、write() メソッドが呼び出され、セッションデータがファイルに書き込まれます。 153session_write_close(); 154 155// 保存されたセッションファイルの内容を確認してみましょう。 156$savedSessionFile = $sessionSavePath . '/' . session_id() . '.sess'; 157if (file_exists($savedSessionFile)) { 158 echo "\n--- 保存されたセッションファイルの内容 ---\n"; 159 echo file_get_contents($savedSessionFile); 160 echo "\n----------------------------------------\n"; 161} else { 162 echo "\nセッションファイル '{$savedSessionFile}' が見つかりませんでした。\n"; 163} 164 165// 注意: このスクリプトを複数回実行すると、同じセッションID(または新しいセッションID)でファイルが上書きされます。 166// セッションの有効期限が切れるか、session_destroy() を呼び出すまでファイルは残ります。 167 168?>
このPHPのサンプルコードは、SessionHandlerInterfaceというインターフェースを実装し、PHPの標準セッション管理を独自の方法で上書きする例です。特に、セッションデータをテキストファイルに保存するカスタムハンドラを構築しています。
SessionHandlerInterfaceに含まれるwriteメソッドは、セッションデータを実際に保存する役割を担います。このメソッドは、セッションデータの変更があった際やセッションが閉じられる際にPHPによって自動的に呼び出されます。引数$idには現在のセッションを一意に識別するための文字列(セッションID)が、引数$dataには保存すべきセッションデータ全体が文字列として渡されます。
サンプルコードのFileSessionHandlerクラスでは、writeメソッド内で受け取った$idと$dataを使用し、$idをファイル名の一部としてセッションデータをテキストファイルに保存しています。具体的には、file_put_contents()関数により、指定されたセッションIDの名前を持つ.sessファイルに$dataの内容を書き込みます。この際、LOCK_EX定数を用いることで、複数のプロセスが同時にファイルへ書き込もうとする際の競合を防ぎます。メソッドの戻り値はbool型で、書き込みが成功した場合はtrue、失敗した場合はfalseをPHPに伝えます。このようにsession_set_save_handler()で登録されたカスタムハンドラは、定義した方法でセッションをテキストファイルへ保存します。
このサンプルコードは、PHPの標準セッション管理をファイルシステムで独自に実装する例です。特に、writeメソッドは、PHPがセッションデータを永続化する際に自動的に呼び出され、指定されたセッションIDとデータをファイルに書き込む役割を果たします。複数のリクエストが同時にセッションにアクセスする場合にデータの破損を防ぐため、file_put_contents関数のLOCK_EXフラグによる排他制御が非常に重要です。また、セッションファイルの保存先ディレクトリの読み書き権限や、書き込み失敗時の適切なエラーハンドリングについても考慮し、堅牢な実装を目指す必要があります。本番環境では、ファイルの代わりにデータベースやKVSの利用が推奨されます。