セッション
同じ人のアクセスをまたいで情報を覚えておくセッションの設定と使い方を説明します。保存先の種類・値の出し入れ・一度だけ使う値・ロック・自作の保存先まで引けます。
HTTP は、1回ごとのやり取りが独立していて、前のやり取りを覚えていません(「ステートレス」といいます)。たとえばログインしても、次のページで、ログインしていたことを忘れてしまいます。セッションは、同じ人から届く何回ものリクエストをまたいで、情報を覚えておくしくみです。お店の「会員カード」のように、来るたびに同じ人だと分かるものです。
覚えておく情報は保存先(バックエンド)に置かれ、あとのリクエストから取り出せます。Laravel には、いろいろな保存先が最初から用意されていて、どれも同じ書き方で使えます。Memcached、Redis(どちらも速いデータの保存先)、データベースなど、よく使われる保存先に対応しています。
設定#
セッションの設定ファイルは、config/session.php です。使えるオプションを、一度見ておくとよいでしょう。ふつう、Laravel は database のセッションドライバ(保存先を扱う部品)を使うように設定されています。
設定の driver オプションは、リクエストごとのセッションのデータを、どこへ保存するかを決めます。使えるドライバは次のとおりです。
| ドライバ | 説明 |
|---|---|
file |
storage/framework/sessions にファイルとして保存する |
cookie |
安全な、暗号化した Cookie(ブラウザに保存される小さなデータ)に保存する |
database |
リレーショナルデータベース(表で管理するデータベース)に保存する |
memcached / redis |
キャッシュを使った、速い保存先のどちらかに保存する |
dynamodb |
AWS の DynamoDB に保存する |
array |
PHP の配列に保存する。ずっとは残らない |
補足
array ドライバは、おもにテスト(プログラムが正しく動くかを確かめるプログラム)で使います。セッションに入れたデータは、どこにも残りません。
ドライバごとに必要なもの#
データベース#
database のドライバを使うときは、セッションのデータを入れるデータベースの表が必要です。この表を作る手順は、ふつう Laravel に最初から入っている 0001_01_01_000000_create_users_table.php のマイグレーション(データベースの表を作ったり変えたりする手順書)に含まれています。もし sessions の表がなければ、make:session-table の Artisan コマンド(php artisan で動かす Laravel のコマンド)で、そのマイグレーションを作れます。
php artisan make:session-table
php artisan migrate
Redis#
Redis をセッションに使う前に、準備が要ります。PECL(PHP の拡張を配るしくみ)で PhpRedis という PHP の拡張(PHP に機能を足す部品)を入れるか、Composer(PHP の部品を入れる道具)で predis/predis のパッケージを入れます。Redis の設定は、Redis の説明を見てください。
補足
セッションに使う Redis の接続は、SESSION_CONNECTION の環境変数(環境ごとに変える設定値)か、session.php の connection オプションで決められます。
セッションを使う#
データを取り出す#
Laravel でセッションのデータを扱う方法は、おもに2つです。どこからでも呼べる session ヘルパー関数を使う方法と、Request のオブジェクトを通す方法です。まず、Request を通す方法を見ます。Request は、ルートのクロージャ(名前のない関数)か、コントローラーのメソッドの引数に、型を書けば受け取れます。コントローラーのメソッドの引数は、サービスコンテナ(クラスを作って渡してくれる道具箱)が自動で渡してくれます。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\View\View;
class UserController extends Controller
{
/**
* Show the profile for the given user.
*/
public function show(Request $request, string $id): View
{
$value = $request->session()->get('key');
// ...
$user = $this->users->find($id);
return view('user.profile', ['user' => $user]);
}
}
セッションから値を取り出すとき、get の2つ目の引数に、初期値を渡せます。そのキーがセッションになければ、この値が返ります。初期値にクロージャを渡すと、キーがないときにそのクロージャが動き、その結果が返ります。
$value = $request->session()->get('key', 'default');
$value = $request->session()->get('key', function () {
return 'default';
});
session ヘルパー関数#
どこからでも呼べる session 関数でも、セッションの読み書きができます。文字を1つだけ渡すと、そのキーの値が返ります。キーと値の配列を渡すと、その値がセッションに保存されます。
Route::get('/home', function () {
// セッションから値を取り出す
$value = session('key');
// 初期値を決める
$value = session('key', 'default');
// セッションに値を保存する
session(['key' => 'value']);
});
補足
HTTP リクエストのオブジェクトを通す方法と、session ヘルパー関数を使う方法に、使う上でのちがいはほとんどありません。どちらの方法でも、テストの中で使える assertSessionHas で確かめられます。
セッションのデータを全部取り出す#
セッションのデータを全部取り出したいときは、all を使います。
$data = $request->session()->all();
セッションのデータの一部を取り出す#
一部だけなら、only と except を使います。
$data = $request->session()->only(['username', 'email']);
$data = $request->session()->except(['username', 'email']);
セッションに値があるか調べる#
セッションに値があるかは、has で調べます。has は、値があり、しかも null ではないときに true を返します。
if ($request->session()->has('users')) {
// ...
}
値が null でも、あるかどうかを知りたいときは、exists を使います。
if ($request->session()->exists('users')) {
// ...
}
値がないことを調べるなら、missing です。値がなければ true を返します。
if ($request->session()->missing('users')) {
// ...
}
データを保存する#
セッションにデータを保存するには、ふつう、リクエストの put メソッドか、session ヘルパー関数を使います。
// リクエストのオブジェクトから
$request->session()->put('key', 'value');
// どこからでも呼べる "session" ヘルパー関数から
session(['key' => 'value']);
配列の値に足す#
push は、中身が配列になっているセッションのデータに、新しい値を足します。たとえば、user.teams のキーに、チームの名前の配列があるなら、次のように足せます。
$request->session()->push('user.teams', 'developers');
取り出して、そのまま消す#
pull は、値の取り出しと消去を、1回でします。
$value = $request->session()->pull('key', 'default');
値を増やす・減らす#
セッションのデータが整数なら、increment と decrement で増やしたり減らしたりできます。
$request->session()->increment('count');
$request->session()->increment('count', $incrementBy = 2);
$request->session()->decrement('count');
$request->session()->decrement('count', $decrementBy = 2);
次のリクエストだけ使う値(フラッシュデータ)#
次のリクエストだけ、セッションに値を残したいことがあります。flash メソッドを使います。この方法で保存した値は、すぐに使えて、次の HTTP リクエストでも使えます。そのあとは消えます。フラッシュデータは、「保存しました」のような、少しの間だけ見せるお知らせに向いています。
$request->session()->flash('status', 'Task was successful!');
フラッシュデータを、いくつかのリクエストにわたって残したいときは、reflash メソッドです。すべてのフラッシュデータを、もう1回のリクエストの間、残せます。特定のものだけ残したいときは、keep メソッドです。
$request->session()->reflash();
$request->session()->keep(['username', 'email']);
フラッシュデータを、いまのリクエストの間だけ残したいときは、now メソッドを使います。
$request->session()->now('status', 'Task was successful!');
データを消す#
forget は、セッションから、データを1つ消します。セッションのデータを全部消したいときは、flush を使います。
// 1つのキーを消す
$request->session()->forget('name');
// 複数のキーを消す
$request->session()->forget(['name', 'status']);
$request->session()->flush();
セッション ID を作り直す#
セッション ID は、セッションを見分ける番号です。この番号は、よく作り直します。悪い人がセッション固定攻撃(相手のセッション ID を決めてしまって、なりすます攻撃)をしかけるのを防ぐためです。
Laravel のスターターキットか、Laravel Fortify(ログイン機能を提供するパッケージ)を使っているなら、ログイン(認証)のときに、Laravel が自動でセッション ID を作り直します。自分で作り直したいときは、regenerate を使います。
$request->session()->regenerate();
セッション ID の作り直しと、セッションのデータの全消去を、1回でしたいときは、invalidate を使います。
$request->session()->invalidate();
| メソッド | 説明 |
|---|---|
get |
値を取り出す(初期値も決められる) |
all |
データを全部取り出す |
only |
指定したキーのデータだけ取り出す |
except |
指定したキー以外のデータを取り出す |
has |
値があり、null ではないか調べる |
exists |
値が null でも、あるか調べる |
missing |
値がないか調べる |
put |
値を保存する |
push |
配列の値に、新しい値を足す |
pull |
値を取り出して、そのまま消す |
increment |
整数の値を増やす |
decrement |
整数の値を減らす |
flash |
次のリクエストまで使える値を保存する |
reflash |
すべてのフラッシュデータを、もう1回のリクエストの間、残す |
keep |
指定したフラッシュデータを、もう1回のリクエストの間、残す |
now |
いまのリクエストの間だけ使える値を保存する |
forget |
指定したキーのデータを消す |
flush |
セッションのデータを全部消す |
regenerate |
セッション ID を作り直す |
invalidate |
セッション ID を作り直し、データも全部消す |
セッションキャッシュ#
セッションキャッシュを使うと、データを1人1人のセッションごとに分けて、キャッシュ(作った結果を取っておくこと)できます。アプリ全体のキャッシュとちがい、データはセッションごとに自動で分かれます。セッションが切れたり消されたりすると、いっしょに片づけられます。get・put・remember・forget など、キャッシュのメソッドがそのまま使えます。ただし、使えるのはいまのセッションの中だけです。
セッションキャッシュに向いているのは、その人だけの一時的なデータです。同じセッションの何回かのリクエストで使いたいけれど、ずっと取っておく必要はないものです。たとえば、フォームのデータ、途中の計算の結果、API の結果などです。
セッションキャッシュは、セッションの cache メソッドで使います。
$discount = $request->session()->cache()->get('discount');
$request->session()->cache()->put(
'discount', 10, now()->plus(minutes: 5)
);
キャッシュのメソッドのくわしくは、キャッシュを見てください。
セッションのブロック#
注意
セッションのブロックを使うには、アトミックロック(同時に1つの処理しか入れないようにする鍵)に対応したキャッシュドライバ(キャッシュの保存先を扱う部品)を使う必要があります。いまは、memcached・dynamodb・redis・mongodb(公式の mongodb/laravel-mongodb パッケージに入っています)・database・file・array のドライバが対応しています。また、セッションのドライバに cookie は使えません。
ふつう、Laravel は、同じセッションのリクエストが同時に動くのを止めません。たとえば、JavaScript の HTTP ライブラリ(通信のための部品)でアプリに2つのリクエストを送ると、2つは同時に動きます。多くのアプリでは、これで困りません。ただ、ごく一部のアプリでは困ることがあります。別々の2つの URL へ同時にリクエストを送り、どちらもセッションにデータを書くと、セッションのデータが消えてしまうことがあるのです。
これを防ぐために、Laravel には、同じセッションの同時のリクエストを制限する機能があります。ルートの定義に、block メソッドをつなぐだけで始められます。次の例では、/profile へのリクエストが、セッションのロック(鍵)を取ります。この鍵を持っているあいだ、同じセッション ID で、/profile か /order へ届いたリクエストは、最初のリクエストが終わるまで待ってから、先へ進みます。
Route::post('/profile', function () {
// ...
})->block($lockSeconds = 10, $waitSeconds = 10);
Route::post('/order', function () {
// ...
})->block($lockSeconds = 10, $waitSeconds = 10);
block は、2つの引数を受け取ります(どちらも省略できます)。1つ目は、セッションの鍵を手放すまでに持っていてよい、いちばん長い秒数です。もちろん、この時間より早くリクエストが終われば、鍵はそのときに手放されます。
2つ目は、リクエストが鍵を取ろうとして待つ秒数です。この秒数のあいだに鍵が取れないと、Illuminate\Contracts\Cache\LockTimeoutException のエラーが起きます。
どちらの引数も渡さなければ、鍵を持てるのは最大10秒、鍵を取るために待つのも最大10秒になります。
Route::post('/profile', function () {
// ...
})->block();
自分でセッションドライバを作る#
ドライバを書く#
いまあるセッションドライバが、アプリに合わないときは、自分でセッションの扱い方(ハンドラ)を書けます。自分で作るセッションドライバは、PHP に最初から入っている SessionHandlerInterface(守るべきメソッドの決まり)に沿って作ります(実装します)。決まっているメソッドは少なく、簡単です。MongoDB(データベースの一種)用の、中身が空のひな形は次のようになります。
<?php
namespace App\Extensions;
class MongoSessionHandler implements \SessionHandlerInterface
{
public function open($savePath, $sessionName) {}
public function close() {}
public function read($sessionId) {}
public function write($sessionId, $data) {}
public function destroy($sessionId) {}
public function gc($lifetime) {}
}
Laravel には、こうした拡張(自分で足す部品)を置く決まったフォルダがありません。好きな場所に置けます。この例では、Extensions というフォルダを作って、MongoSessionHandler を入れました。
それぞれのメソッドの目的が分かりにくいので、役割をまとめます。
| メソッド | 説明 |
|---|---|
open |
ファイルを使うセッションの保存先で使う。Laravel には file ドライバがあるので、ほとんど書かなくてよい。空のままでよい |
close |
open と同じで、ふつうは無視してよい。たいていのドライバでは要らない |
read |
渡された $sessionId に結びついた、セッションのデータを、文字で返す。保存と取り出しで、変換(シリアライズなど)は要らない。Laravel がやってくれる |
write |
$sessionId に結びついた $data の文字を、MongoDB などの、ずっと残る保存先へ書く。ここでも変換は不要。Laravel が済ませている |
destroy |
$sessionId に結びついたデータを、保存先から消す |
gc |
渡された $lifetime(秒数)より古い、セッションのデータをすべて消す。Memcached や Redis のように、自分で期限が切れる保存先では、空のままでよい |
ドライバを登録する#
ドライバを書いたら、Laravel に登録します。Laravel のセッションの保存先に、ドライバを足すには、Session のファサード(クラス名と :: で呼べる窓口)の extend メソッドを使います。extend は、サービスプロバイダ(アプリの起動のときに、道具箱へ道具を登録する場所)の boot メソッドから呼びます。いまある App\Providers\AppServiceProvider に書いても、まったく新しいプロバイダを作ってもかまいません。
<?php
namespace App\Providers;
use App\Extensions\MongoSessionHandler;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\ServiceProvider;
class SessionServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*/
public function register(): void
{
// ...
}
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Session::extend('mongo', function (Application $app) {
// SessionHandlerInterface を実装したものを返す
return new MongoSessionHandler;
});
}
}
セッションドライバを登録したら、SESSION_DRIVER の環境変数か、config/session.php の設定ファイルで、アプリのセッションドライバを mongo にできます。
関連するページ#
公式ドキュメント(英語)
2026年10月5日時点の内容をもとに、日本語でまとめています。