イントロダクション

HTTP駆動のアプリケーションはステートレスですから、リクエスト間に渡り情報を保存するセッションが提供されています。Laravelは美しく統一されたAPIを使える様々なバックエンドのセッションを用意しています。人気のあるMemcachedRedis、データベースも始めからサポートしています。

設定

セッションの設定はconfig/session.phpにあります。このファイルのオプションには詳しくコメントがついていますので確認して下さい。ほとんどのアプリケーションでうまく動作できるように、Laravelはfileセッションドライバーをデフォルトとして設定しています。実働環境のアプリケーションではセッションの動作をより早くするために、memcachedredisドライバーの使用を考慮しましょう。

セッションドライバー(driver)はリクエスト毎のセッションデータをどこに保存するかを決めます。Laravelには最初から素晴らしいドライバーが用意されています。

file - セッションはstorage/framework/sessionsに保存されます。
cookie - セションは暗号化され安全なクッキーに保存されます。
database - セッションはアプリケーションで使用しているデータベースに保存されます。
memcachedredis - セッションはスピードの早いキャッシュベースの保存域に保存されます。
array - セッションは単にPHPの配列として保存されるだけで、リクエスト間で継続しません。

注意: セッションデータが持続しないように、arrayドライバーは通常テストの実行で使用されます。

ドライバーの事前要件

データベース

databaseセッションドライバーを使う場合、セッションアイテムを含むテーブルを準備する必要があります。以下にこのテーブル宣言のサンプル「スキーマ」を示します。

Schema::create('sessions', function ($table) {
    $table->string('id')->unique();
    $table->text('payload');
    $table->integer('last_activity');
});

session:table Artisanコマンドを使えば、このマイグレーションが生成できます!

php artisan session:table

composer dump-autoload

php artisan migrate

Redis

ReidsセッションをLaravelで使用する前に、Composerでpredis/predisパッケージ(~1.0)をインストールする必要があります。

その他セッションでの考慮点

Laravelフレームワークはflashセッションキーを内部で使用しているため、この名前でアイテムをセッションに追加してはいけません。

セッションに保存する全データを暗号化したい場合、encrypt設定オプションをtrueに指定してください。

基本的な使用法

セッションへのアクセス

最初にセッションへアクセスしてみましょう。コントローラーメソッドでタイプヒントを指定し、HTTPリクエストを経由してセッションをインスタンスへアクセスできます。コントローラーメソッドの依存はLaravelのサービスコンテナにより注入されることを覚えておきましょう。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class UserController extends Controller
{
    /**
     * 指定ユーザーのプロフィールを表示
     *
     * @param  Request  $request
     * @param  int  $id
     * @return Response
     */
    public function showProfile(Request $request, $id)
    {
        $value = $request->session()->get('key');

        //
    }
}

セッションから値を取得するときに、getメソッドの第2引数としてデフォルト値を渡せます。このデフォルト値は指定したキーがセッションに存在していない場合に返されます。デフォルト値として「クロージャー」をgetメソッドへ渡す場合、その「クロージャー」の実行結果が返されます。

$value = $request->session()->get('key', 'default');

$value = $request->session()->get('key', function() {
    return 'default';
});

セッションから全データを取得したい場合は、allメソッドを使用してください。

$data = $request->session()->all();

セッションから取得したり、保存したりするためにグローバルのsessionヘルパー関数を使用することができます。

Route::get('home', function () {
    // セッションからデータを一つ取得…
    $value = session('key');

    // セッションへデータ一つを保存…
    session(['key' => 'value']);
});

セッション中のアイテム存在を確認

hasメソッドでセッションにアイテムが存在するかを調べられます。このメソッドは存在している場合にtrueを返します。

if ($request->session()->has('users')) {
    //
}

セッションへのデータ保存

セッションインスタンスへアクセスしたら、データを操作するために数々のメソッドを呼び出せます。たとえば新しいデータをセッションへ保存するにはputを使います。

$request->session()->put('key', 'value');

配列セッション値の追加

pushメソッドは新しい値を配列のセッション値へ追加します。たとえばuser.teamsキーにチーム名の配列が含まれているなら、新しい値を次のように追加できます。

$request->session()->push('user.teams', 'developers');

取得後アイテムを削除

pullメソッドでセッションからアイテムを取得後、削除できます。

$value = $request->session()->pull('key', 'default');

セッションからアイテムを削除

forgetメソッドでセッションからデータを削除できます。セッションから全データを削除したければ、flushメソッドが使用できます。

$request->session()->forget('key');

$request->session()->flush();

セッションIDの再生成

セッションIDを再生成する必要がある場合、regenerateメソッドを使ってください。

$request->session()->regenerate();

フラッシュデータ

次のリクエスト間だけセッションにアイテムを保存したいことは良くあります。flashメソッドを使ってください。flashメソッドは直後のHTTPリクエストの間だけセッションにデータを保存します。それ以降は削除されます。フラッシュデータは主にステータスメッセージなど継続しない情報に便利です。

$request->session()->flash('status', 'タスクは成功しました!');

フラッシュデータをさらにその先のリクエストまで持続させたい場合は、reflashメソッドを使い全フラッシュデータをその先のリクエストまで持続させられます。特定のフラッシュデータのみ持続させたい場合は、keepメソッドを使います。

$request->session()->reflash();

$request->session()->keep(['username', 'email']);

カスタムセッションドライバーの追加

Laravelのセッションのバックエンドにドライバーを追加したい場合、Sessionファサードextendメソッドを使用します。サービスプロバイダーbootメソッドからextendメソッドを呼び出してください。

<?php

namespace App\Providers;

use Session;
use App\Extensions\MongoSessionStore;
use Illuminate\Support\ServiceProvider;

class SessionServiceProvider extends ServiceProvider
{
    /**
     * サービスの初期処理登録後に実行
     *
     * @return void
     */
    public function boot()
    {
        Session::extend('mongo', function($app) {
            // SessionHandlerInterfaceの実装を返す…
            return new MongoSessionStore;
        });
    }

    /**
     * コンテナに結合を登録
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

カスタムセッションドライバーはSessionHandlerInterfaceを実装している点に注意してください。このインターフェイスは実装が必要なシンプルなメソッドで構成されています。MongoDBのスタブ実装は次のようになるでしょう。

<?php

namespace App\Extensions;

class MongoHandler 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) {}
}

キャッシュの「保存インターフェイス」として、これらのメソッドは理解しづらいでしょうから簡単に各メソッドを説明します。

openメソッドは通常ファイルベースのセッション保存システムで使われます。Laravelはfileセッションドライバーを用意していますが、皆さんはこのメソッドに何も入れる必要はないでしょう。空のスタブのままで良いでしょう。実際、PHPが実装するように要求しているこのメソッドは、下手なインターフェイスデザインなのです。
closeメソッドもopenと同様に通常は無視できます。ほどんどのドライバーでは必要ありません。
readメソッドは指定された$sessionIdと紐付いたセッションデータの文字列バージョンを返します。取得や保存時にドライバー中でデータをシリアライズしたり、他のエンコード作業を行ったりする必要はありません。Laravelがシリアライズを行います。
writeメソッドはMongoDBやDynamoなどの持続可能なストレージに、$sessionIdに紐付け指定した$data文字列を書き出します。
destroyメソッドは持続可能なストレージから$sessionIdに紐付いたデータを取り除きます。
gcメソッドは指定したUNIXタイムスタンプの$lifetimeよりも古い前セッションデータを削除します。自前で破棄するMemcachedやRedisのようなシステムでは、このメソッドは空のままにしておきます。

セッションドライバーを登録したら、config/session.php設定ファイルでmongoドライバーが使用できます。