はじめに
セッションハンドラでセッション管理をしていたときに**session_start()**を呼び出すと下記エラーが発生。
session_start(): Failed to read session data: user (path: /var/lib/php/session) in ...
本記事ではエラーの原因、解決方法を備考録としてまとめております。
原因
セッションハンドラ実装の流れ
-
session_set_save_handler関数を定義
関数の説明は公式を参照 -
session_set_save_handler関数にSessionHandlerInterfaceインタフェースを実装したクラスのオブジェクトを渡す
-
SessionHandlerInterfaceを実装するには、以下の6つのメソッドを実装する
close(): bool
destroy(string $sessionId): bool
gc(int $lifetime): bool
open(string $savePath, string $sessionName): bool
read(string $sessionId): string
write(string $sessionId, string $data): bool
今回のエラーの原因はFailed to read session data〜
の通り、readメソッドの部分が該当していると読み取れる。公式のsession_start関数にてエラー文言について触れている部分がないか検索すると、下記内容が見つかる。
If you are using a custom session handler via session_set_save_handler() then calling session_start() in PHP 7.1 you might see an error like this:
session_start(): Failed to read session data: user (path: /var/lib/php/session) in ...
As of this writing, it seems to be happening in PHP 7.1, and things look OK in PHP7.0.
It is also hard to track down because if a session already exists for this id (maybe created by an earlier version of PHP), it will not trigger this issue because the $session_data will not be null.
The fix is simple... you just need to check for 'null' during your read function:
<?php
function read($id)
{
//... pull the data out of the DB, off the disk, memcache, etc
$session_data = getSessionDataFromSomewhere($id);
//check to see if $session_data is null before returning (CRITICAL)
if(is_null($session_data))
{
$session_data = ''; //use empty string instead of null!
}
return $session_data;
}
?>
どうやら、戻り値がnull今回のエラーが発生する模様。。
解決方法
先の検索結果を参考に、戻り値がnullかどうかをチェックしてnullの場合は空文字を返す。
//check to see if $session_data is null before returning (CRITICAL)
if(is_null($session_data))
{
$session_data = ''; //use empty string instead of null!
}
return $session_data;
終わりに
readメソッドでDBの取得が0件の時に戻り値をnullにしていたため今回のエラーが発生しておりました。エラー事象を解決した後に、公式のreadメソッドの説明を眺めていたら、しっかり取得データがないときは空文字を返却するよう記載があった。。
read コールバックは、常にセッションエンコード (シリアライズ) された文字列を返さなければなりません。何もデータを読み込まなかった場合は空文字列を返します。