Lang x Lang

HTTP Session

Table of Contents

Introduction

HTTP 駆動型のアプリケーションはステートレスであるため、セッションは複数のリクエストにわたる user に関する情報を保存する方法を提供します。その user の情報は、通常、後続のリクエストからアクセスできる永続的なストア / バックエンドに配置されます。

Laravel は、表現力豊かで統一された API を通じてアクセスされる、様々な session バックエンドを標準装備しています。 Memcached Redis 、そしてデータベースのような人気のバックエンドに対応しています。

Configuration

あなたのアプリケーションの session 設定ファイルは config/session.php に保存されています。このファイル内の利用可能な options を確認するようにしてください。 default では、 Laravel は database session driver を使用するように設定されています。

session driver設定オプションは、各 request に対して session data がどこに保存されるかを定義します。 Laravel には様々なドライバーが含まれています:

  • file - セッションは storage/framework/sessions に保存されます。
  • cookie - セッションは、安全で暗号化されたクッキーに保存されます。
  • database - セッションは関係性のある database に保存されます。
  • memcached / redis - セッションは、これらの高速で、 cache ベースのストアのいずれかに保存されます。
  • dynamodb - セッションは AWS DynamoDB に保存されます。
  • array - セッションは PHP の array に保存され、永続化されません。

NOTE

array driver は主にtesting中に使用され、保存されている data が session に永続化されるのを防ぎます。

Driver Prerequisites

Database

databaseの session driver を使用する際には、session data を含む database テーブルが存在することを確認する必要があります。通常、これは Laravel の default 0001_01_01_000000_create_users_table.php database migrationに含まれています。しかし、何らかの理由でsessionsテーブルがない場合は、make:session-table Artisan command を使用してこのマイグレーションを生成することができます:

php artisan make:session-table

php artisan migrate

Redis

Redissessions を Laravel で使用する前に、PECL 経由で PhpRedis PHP 拡張をインストールするか、predis/predisパッケージ(〜1.0)を Composer 経由でインストールする必要があります。 Redis の設定についての詳細は、Laravel のRedis ドキュメンテーションをご覧ください。

NOTE

SESSION_CONNECTION 環境 variables、または session.php 設定ファイルの connection option を使用して、どの Redis 接続が sessionstorage に使用されるかを指定できます。

Interacting With the Session

Data の取得

二つの primary な方法が存在し、 session data を Laravel で扱うためにはグローバルなsessionヘルパーとRequestインスタンスがあります。まずは、Requestインスタンスを通じて session にアクセスする方法を見てみましょう。この方法は、 route クロージャまたは controller method に入力ヒントを与えることができます。そして覚えておいてください、 controller method の依存関係は自動的に Laravel のservice containerが注入されます。

<?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]);
    }
}

あなたが session からアイテムを取得する際、get method の第二引数として default value を渡すことも可能です。この default value は、指定されたキーが session に存在しない場合に返されます。get method に default value としてクロージャを渡し、要求されたキーが存在しない場合、そのクロージャは実行され、その結果が返されます。

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

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

グローバル Session ヘルパー

あなたはまた、グローバルな session PHP 関数を使用して、 data を session に取得し保存することもできます。session ヘルパーが single の string 引数で呼び出された場合、その session キーの value が返されます。ヘルパーがキー/ value のペアの array で呼び出された場合、それらの values は session に保存されます。

Route::get('/home', function () {
    // Retrieve a piece of data from the session...
    $value = session('key');

    // Specifying a default value...
    $value = session('key', 'default');

    // Store a piece of data in the session...
    session(['key' => 'value']);
});

NOTE

HTTP requestインスタンス経由で session を使用するのと、グローバルsessionヘルパーを使用するのとの間には実質的な違いはほとんどありません。どちらの方法も、すべてのテストケースで利用可能な assertSessionHas method を介してテスト可能です。

すべての Session Data を取得する

もしすべての data を session から取得したい場合は、all method を使用することができます。

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

Session Data の一部を取得する

onlyおよびexceptメソッドは、 session data の一部を取得するために使用できます:

$data = $request->session()->only(['username', 'email']);

$data = $request->session()->except(['username', 'email']);

Session 内にアイテムが存在するかどうかの判断

アイテムが session に存在するかどうかを判断するために、has method を使用することができます。 has method は、アイテムが存在し、nullでない場合にtrueを返します。

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

ある項目が session に存在するかどうかを判断するには、その value がnullであっても、exists method を使用できます:

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

アイテムが session に存在しないかどうかを判断するには、missing method を使用できます。 missing method は、アイテムが存在しない場合にtrueを返します。

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

Data の保存

data を session に保存するためには、通常、 request インスタンスのput method またはグローバルなsessionhelper を使用します。

// Via a request instance...
$request->session()->put('key', 'value');

// Via the global "session" helper...
session(['key' => 'value']);

Array Session Values へのプッシュ

push method は、 array である session value に新しい value をプッシュするために使用できます。例えば、user.teamskey がチーム名の array を含んでいる場合、以下のように新しい value を array にプッシュできます:

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

アイテムの取得と Deleting

pull method は、シングル statement で session からアイテムを取得し削除します。

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

Session Values の増分と減分

もし、あなたの session data が、増減させたい integer を含んでいるなら、incrementdecrementmethod を使用することができます:

$request->session()->increment('count');

$request->session()->increment('count', $incrementBy = 2);

$request->session()->decrement('count');

$request->session()->decrement('count', $decrementBy = 2);

フラッシュ Data

時々、次の request のためにアイテムを session に保存したいと思うかもしれません。flash method を使用してこれを行うことができます。この method を使用して session に保存された Data はすぐに利用可能で、続く HTTP request の間も利用可能です。その次の HTTP request 後には、フラッシュされた data は削除されます。フラッシュ data は主に短命の status メッセージに役立ちます:

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

もし複数の request のためにフラッシュ data を保持する必要がある場合は、reflash method を使用することで、全てのフラッシュ data を追加の request のために保持することができます。特定のフラッシュ data だけを保持する必要がある場合は、keep method を使用することができます。

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

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

現在の request のみに対してフラッシュ data を永続化するために、now method を使用することができます:

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

Deleting Data

forget method は、 session から 1 つの data を削除します。もし session からすべての data を削除したい場合は、flush method を使用することができます。

// Forget a single key...
$request->session()->forget('name');

// Forget multiple keys...
$request->session()->forget(['name', 'status']);

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

Session ID の再生成

session ID を再生成することは、悪意のある users があなたの application に対してsession 固定 攻撃を悪用するのを防ぐためによく行われます。

Laravel は、 Laravel のapplication スターターキットあるいはLaravel Fortifyを使用している場合、 authentication 中に自動的に session ID を再生成します。しかし、手動で session ID を再生成する必要がある場合、regenerate method を使用することができます。

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

もし session ID を再生成し、 session から全ての data を single statement で削除する必要がある場合、invalidate method を利用することができます:

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

Session Blocking

WARNING

session ブロッキングを利用するには、あなたの application はatomic locksをサポートする cache driver を使用している必要があります。現在、そのような cache ドライバには、memcacheddynamodbredisdatabasefilearrayドライバが含まれます。さらに、cookieの session driver は使用できません。

default で、 Laravel は同じ session を使用したリクエストが concurrently で実行されることを許可しています。したがって、例えば JavaScript HTTP library を使って二つの HTTP requests をあなたの application に対して行った場合、それらは同時に実行されます。多くのアプリケーションではこれは問題ではありませんが、 session data の損失は、異なる二つの application エンドポイントに対して同時にリクエストを行い、両方が session に data を書き込むようなアプリケーションの一部で発生する可能性があります。

これを軽減するために、 Laravel は、特定の session に対する同時リクエストを制限する機能を提供します。始めるには、block method をあなたの route 定義に単純にチェインするだけです。この例では、/profileエンドポイントへの入力 request が session のロックを取得します。このロックが保持されている間、同じ session ID を共有する/profileまたは/orderエンドポイントへの他の入力リクエストは、最初の request が実行を終了するのを待ってから実行を続行します。

Route::post('/profile', function () {
    // ...
})->block($lockSeconds = 10, $waitSeconds = 10)

Route::post('/order', function () {
    // ...
})->block($lockSeconds = 10, $waitSeconds = 10)

block method は、二つの option の引数を受け付けます。block method によって最初に受け入れられる引数は、 session ロックが開放される前に維持されるべき最大の秒数です。もちろん、もし request がこの時間前に実行を終えれば、ロックはより早く解放されます。

block method が受け付ける第二引数は、 session のロックを取得しようとする際に request が待懸命になるべき秒数です。指定された秒数内に request が session のロックを取得できない場合、Illuminate\Contracts\Cache\LockTimeoutExceptionが throw されます。

これらの引数のいずれも渡されない場合、ロックは最大 10 秒間取得され、ロックの取得を試みる間、リクエストは最大 10 秒間待機します:

Route::post('/profile', function () {
    // ...
})->block()

Adding Custom Session Drivers

Driver の実装

既存の sessiondrivers があなたの application のニーズに合わない場合、Laravel を使用すると、独自の session handler を記述することが可能です。あなたの custom session driver は、PHP の組み込みのSessionHandlerInterfaceを実装する必要があります。このインターフェースには、いくつかの単純な method が含まれています。スタブ化された 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) {}
}

NOTE

Laravel は、 extensions を格納するディレクトリを標準で提供していません。あなたは好きな場所にそれらを配置することができます。この例では、MongoSessionHandlerを保存するためのExtensionsディレクトリを作成しました。

これらのメソッドの目的がすぐに理解できないため、それぞれのメソッドが何をするのかを簡単に説明しましょう:

  • open method は、通常、ファイルベースの session ストアシステムで使用されます。 Laravel はfileの session driver を標準で提供しているため、この method に何かを入れる必要はほとんどありません。この method は空のままにしておくことができます。
  • close method は、open method と同様に、通常は無視できます。ほとんどの driver では、それは必要ではありません。
  • read method は、与えられた $sessionId に関連付けられた session data の string version を返すべきです。 session data をあなたの driver で取得または格納する際に、直列化や他のエンコーディングをする必要はありません。なぜなら、 Laravel が直列化を行ってくれるからです。
  • write method は与えられた$data string を$sessionIdと関連付けて、MongoDB や他の選択した storage システムなどの永続的な storage システムに書き込むべきです。再度、任意のシリアライゼーションを実行しないでください - Laravel がすでにそれを処理してくれています。
  • destroy method は、$sessionIdに関連付けられた data を永続的な storage から削除するべきです。
  • gc method は、与えられた $lifetimeよりも古い全ての session data を破棄するべきです。これは UNIX の timestamp です。自身で有効期限が切れるシステム、例えば Memcached や Redis のようなものでは、この method は空のままにしておくことも可能です。

Registering the Driver

driver が実装されたら、それを Laravel に register する準備が整いました。Laravel の session バックエンドに追加の driver を追加するためには、Session facade によって提供される extend method を使用することができます。extend method は、service providerboot method から呼び出すべきです。既存の App\Providers\AppServiceProviderから行うか、全く新しい provider を作成して行うことができます:

<?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) {
            // Return an implementation of SessionHandlerInterface...
            return new MongoSessionHandler;
        });
    }
}

一旦 session driver が登録されると、mongo driver をアプリケーションの session driver として指定できます。これは、SESSION_DRIVER environment 変数またはアプリケーションの config/session.php 構成ファイル内で行うことができます。

当社サイトでは、Cookie を使用しています。各規約をご確認の上ご利用ください:
Cookie Policy, Privacy Policy および Terms of Use