Laravel5.5 LTS 日本語ドキュメント

このリポジトリはPHP Webアプリフレームワークである、LaravelのLTSバージョンである5.5の公式英文ドキュメントを日本語へ翻訳しています。

This project is maintained by okinaka

HTTPセッション

イントロダクション

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

設定

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

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

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

{tip} セッションデータを持続させないため、arrayドライバは通常テスト時に使用します。

ドライバの事前要件

データベース

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

Schema::create('sessions', function ($table) {
    $table->string('id')->unique();
    $table->unsignedInteger('user_id')->nullable();
    $table->string('ip_address', 45)->nullable();
    $table->text('user_agent')->nullable();
    $table->text('payload');
    $table->integer('last_activity');
});

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

php artisan session:table

php artisan migrate

Redis

ReidsセッションをLaravelで使用する前に、Composerでpredis/predisパッケージ(~1.0)をインストールする必要があります。Redis接続はdatabase設定ファイルで設定します。session設定ファイルでは、connectionオプションで、どのRedis接続をセッションで使用するか指定します。

セッションの使用

データ取得

Laravelでセッションを操作するには、主に2つの方法があります。グローバルなsessionヘルパを使用する方法と、コントローラメソッドにタイプヒントで指定できるRequestインスタンスを経由する方法です。最初はRequestインスタンスを経由する方法を見てみましょう。コントローラのメソッドに指定した依存インスタンスは、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 show(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';
});

sessionグローバルヘルパ

グローバルなsession PHP関数で、セッションからデータを出し入れすることもできます。sessionヘルパが文字列ひとつだけで呼び出されると、そのセッションキーに対する値を返します。ヘルパがキー/値ペアの配列で呼び出されると、それらの値はセッションへ保存されます。

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

    // デフォルト値を指定する場合
    $value = session('key', 'default');

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

{tip} セッションをHTTPリクエストインスタンスを経由する場合と、グローバルなsessionヘルパを使用する場合では、実践上の違いがあります。どんなテストケースであろうとも使用可能な、assertSessionHasメソッドを利用して、どちらの手法もテスト可能です。

全セッションデータの取得

セッション中の全データを取得する場合は、allメソッドを使います。

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

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

セッションへ値が存在するか調べたい場合は、hasメソッドを使います。その値が存在し、nullでない場合はtrueが返ります。

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

セッション中に、たとえ値がnullであろうとも存在していることを確認したい場合は、existsメソッドを使います。existsメソッドは、値が存在していればtrueを返します。

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

データ保存

セッションへデータを保存する場合、通常putメソッドか、sessionヘルパを使用します。

// リクエストインスタンス経由
$request->session()->put('key', 'value');

// グローバルヘルパ使用
session(['key' => 'value']);

配列セッション値の追加

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

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

取得後アイテムを削除

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

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

フラッシュデータ

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

$request->session()->flash('status', 'Task was successful!');

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

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

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

データ削除

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

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

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

セッションIDの再生性

セッションIDの再生成は多くの場合、悪意のあるユーザーからの、アプリケーションに対するsession fixation攻撃を防ぐために行います。

Laravelに組み込まれているLoginControllerを使用していれば、認証中にセッションIDは自動的に再生性されます。しかし、セッションIDを任意に再生成する必要があるのでしたら、regenerateメソッドを使ってください。

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

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

ドライバの実装

カスタムセッションドライバでは、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) {}
}

{tip} こうした拡張を含むディレクトリをLaravelでは用意していません。お好きな場所に設置してください。上記の例では、Extensionディレクトリを作成し、MongoSessionHandlerファイルを設置しています。

これらのメソッドの目的を読んだだけでは理解しづらいため、それぞれのメソッドを簡単に見てみましょう。

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

ドライバの登録

ドライバを実装したら、フレームワークへ登録する準備が整いました。Laravelのセッションバックエンドへドライバを追加するには、Sessionファサードextendメソッドを呼び出します。サービスプロバイダbootメソッドから、extendメソッドを呼び出してください。既存のAppServiceProviderか真新しく作成し、呼び出してください。

<?php

namespace App\Providers;

use App\Extensions\MongoSessionHandler;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\ServiceProvider;

class SessionServiceProvider extends ServiceProvider
{
    /**
     * サービス起動処理の事前登録
     *
     * @return void
     */
    public function boot()
    {
        Session::extend('mongo', function ($app) {
            // SessionHandlerInterfaceの実装を返す…
            return new MongoSessionHandler;
        });
    }

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

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