イントロダクションIntroduction
HTTP駆動のアプリケーションはステートレスのため、リクエスト間に渡りユーザーに関する情報を保存するセッションが提供されています。Laravelは記述的で統一されたAPIを使えるさまざまなバックエンドのセッションを用意しています。人気のあるMemcachedやRedis、データベースも始めからサポートしています。Since HTTP driven applications are stateless, sessions provide a way to store information about the user across multiple requests. Laravel ships with a variety of session backends that are accessed through an expressive, unified API. Support for popular backends such as Memcached[https://memcached.org], Redis[https://redis.io], and databases is included out of the box.
設定Configuration
セッションの設定はconfig/session.php
にあります。このファイルのオプションには詳しくコメントがついていますので確認してください。ほとんどのアプリケーションでうまく動作できるように、Laravelはfile
セッションドライバをデフォルトとして設定しています。The session configuration file is stored at config/session.php
. Be sure to review the options available to you in this file. By default, Laravel is configured to use the file
session driver, which will work well for many applications.
セッションドライバ(driver
)はリクエスト毎のセッションデータをどこに保存するかを決めます。Laravelには最初から素晴らしいドライバが用意されています。The session driver
configuration option defines where session data will be stored for each request. Laravel ships with several great drivers out of the box:
テスト時に使用します。{tip} The array driver is used during testing[/docs/{{version}}/testing] and prevents the data stored in the session from being persisted.
">Tip!! セッションデータを持続させないため、arrayドライバは通常
ドライバの事前要件Driver Prerequisites
データベースDatabase
database
セッションドライバを使う場合、セッションアイテムを含むテーブルを作成する必要があります。以下にこのテーブル宣言のサンプル「スキーマ」を示します。When using the database
session driver, you will need to create a table to contain the session items. Below is an example Schema
declaration for the table:
Schema::create('sessions', function ($table) {
$table->string('id')->unique();
$table->foreignId('user_id')->nullable();
$table->string('ip_address', 45)->nullable();
$table->text('user_agent')->nullable();
$table->text('payload');
$table->integer('last_activity');
});
session:table
Artisanコマンドを使えば、このマイグレーションが生成できます。You may use the session:table
Artisan command to generate this migration:
php artisan session:table
php artisan migrate
RedisRedis
RedisセッションをLaravelで使用する前に、PECLによりPhpRedis PHP拡張、もしくはComposerでpredis/predis
パッケージ(~1.0)をインストールする必要があります。Redis設定の詳細は、Laravelのドキュメントをご覧ください。Before using Redis sessions with Laravel, you will need to either install the PhpRedis PHP extension via PECL or install the predis/predis
package (~1.0) via Composer. For more information on configuring Redis, consult its Laravel documentation page[/docs/{{version}}/redis#configuration].
">Tip!!
session
設定ファイルでは、connection
オプションで、どのRedis接続をセッションで使用するか指定します。{tip} In thesession
configuration file, theconnection
option may be used to specify which Redis connection is used by the session.
セッションの使用Using The Session
データ取得Retrieving Data
Laravelでセッションを操作するには、主に2つの方法があります。グローバルなsession
ヘルパを使用する方法と、コントローラメソッドにタイプヒントで指定できるRequest
インスタンスを経由する方法です。最初はRequest
インスタンスを経由する方法を見てみましょう。コントローラのメソッドに指定した依存インスタンスは、Laravelのサービスコンテナにより、自動的に注入されることを覚えておきましょう。There are two primary ways of working with session data in Laravel: the global session
helper and via a Request
instance. First, let's look at accessing the session via a Request
instance, which can be type-hinted on a controller method. Remember, controller method dependencies are automatically injected via the Laravel service container[/docs/{{version}}/container]:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
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
メソッドのデフォルト値に「クロージャ」を渡した場合に、要求したキーが存在しなければ、その「クロージャ」が実行され、結果が返されます。When you retrieve an item from the session, you may also pass a default value as the second argument to the get
method. This default value will be returned if the specified key does not exist in the session. If you pass a Closure
as the default value to the get
method and the requested key does not exist, the Closure
will be executed and its result returned:
$value = $request->session()->get('key', 'default');
$value = $request->session()->get('key', function () {
return 'default';
});
sessionグローバルヘルパThe Global Session Helper
グローバルなsession
PHP関数で、セッションからデータを出し入れすることもできます。session
ヘルパが文字列ひとつだけで呼び出されると、そのセッションキーに対する値を返します。ヘルパがキー/値ペアの配列で呼び出されると、それらの値はセッションへ保存されます。You may also use the global session
PHP function to retrieve and store data in the session. When the session
helper is called with a single, string argument, it will return the value of that session key. When the helper is called with an array of key / value pairs, those values will be stored in the session:
Route::get('home', function () {
// セッションから一つのデータを取得する
$value = session('key');
// デフォルト値を指定する場合
$value = session('key', 'default');
// セッションへ一つのデータを保存する
session(['key' => 'value']);
});
">Tip!! セッションをHTTPリクエストインスタンスを経由する場合と、グローバルな
session
ヘルパを使用する場合では、実践上の違いがあります。どんなテストケースであろうとも使用可能な、assertSessionHas
メソッドを利用して、どちらの手法もテスト可能です。{tip} There is little practical difference between using the session via an HTTP request instance versus using the globalsession
helper. Both methods are testable[/docs/{{version}}/testing] via theassertSessionHas
method which is available in all of your test cases.
全セッションデータの取得Retrieving All Session Data
セッション中の全データを取得する場合は、all
メソッドを使います。If you would like to retrieve all the data in the session, you may use the all
method:
$data = $request->session()->all();
セッション中のアイテム存在を確認Determining If An Item Exists In The Session
セッションへ値が存在するか調べたい場合は、has
メソッドを使います。その値が存在し、null
でない場合はtrue
が返ります。To determine if an item is present in the session, you may use the has
method. The has
method returns true
if the item is present and is not null
:
if ($request->session()->has('users')) {
//
}
セッション中に、たとえ値がnull
であろうとも存在していることを確認したい場合は、exists
メソッドを使います。exists
メソッドは、値が存在していればtrue
を返します。To determine if an item is present in the session, even if its value is null
, you may use the exists
method. The exists
method returns true
if the item is present:
if ($request->session()->exists('users')) {
//
}
データ保存Storing Data
セッションへデータを保存する場合、通常put
メソッドか、session
ヘルパを使用します。To store data in the session, you will typically use the put
method or the session
helper:
// リクエストインスタンス経由
$request->session()->put('key', 'value');
// グローバルヘルパ使用
session(['key' => 'value']);
配列セッション値の追加Pushing To Array Session Values
push
メソッドは新しい値を配列のセッション値へ追加します。たとえばuser.teams
キーにチーム名の配列が含まれているなら、新しい値を次のように追加できます。The push
method may be used to push a new value onto a session value that is an array. For example, if the user.teams
key contains an array of team names, you may push a new value onto the array like so:
$request->session()->push('user.teams', 'developers');
取得後アイテムを削除Retrieving & Deleting An Item
pull
メソッド一つで、セッションからアイテムを取得後、削除できます。The pull
method will retrieve and delete an item from the session in a single statement:
$value = $request->session()->pull('key', 'default');
フラッシュデータFlash Data
次のリクエスト間だけセッションにアイテムを保存したいことがあります。flash
メソッドを使ってください。flash
メソッドは現在と直後のHTTPリクエストの間だけ、セッションにデータを保存し、それ以降は削除します。フラッシュデータは主にステータスメッセージなど、持続しない情報に便利です。Sometimes you may wish to store items in the session only for the next request. You may do so using the flash
method. Data stored in the session using this method will be available immediately and during the subsequent HTTP request. After the subsequent HTTP request, the flashed data will be deleted. Flash data is primarily useful for short-lived status messages:
$request->session()->flash('status', 'Task was successful!');
フラッシュデータをその先のリクエストまで持続させたい場合は、reflash
メソッドを使い、全フラッシュデータを次のリクエストまで持続させられます。特定のフラッシュデータのみ持続させたい場合は、keep
メソッドを使います。If you need to keep your flash data around for several requests, you may use the reflash
method, which will keep all of the flash data for an additional request. If you only need to keep specific flash data, you may use the keep
method:
$request->session()->reflash();
$request->session()->keep(['username', 'email']);
データ削除Deleting Data
forget
メソッドでセッションからデータを削除できます。セッションから全データを削除したければ、flush
メソッドが使用できます。The forget
method will remove a piece of data from the session. If you would like to remove all data from the session, you may use the flush
method:
// 1キーを削除
$request->session()->forget('key');
// 複数キーを削除
$request->session()->forget(['key1', 'key2']);
$request->session()->flush();
セッションIDの再生成Regenerating The Session ID
セッションIDの再生成は多くの場合、悪意のあるユーザーからの、アプリケーションに対するsession fixation攻撃を防ぐために行います。Regenerating the session ID is often done in order to prevent malicious users from exploiting a session fixation[https://owasp.org/www-community/attacks/Session_fixation] attack on your application.
Laravelに組み込まれているLoginController
を使用していれば、認証中にセッションIDは自動的に再生成されます。しかし、セッションIDを任意に再生成する必要があるのでしたら、regenerate
メソッドを使ってください。Laravel automatically regenerates the session ID during authentication if you are using the built-in LoginController
; however, if you need to manually regenerate the session ID, you may use the regenerate
method.
$request->session()->regenerate();
セッションのブロックSession Blocking
Note: アトミックロックをサポートするキャッシュドライバを使用する必用があります。現在、
セッションのブロックを使用するには、memcached
、dynamodb
、redis
、database
のキャッシュドライバがサポートしています。さらに、cookie
セッションドライバは使用できません。{note} To utilize session blocking, your application must be using a cache driver that supports atomic locks[/docs/{{version}}/cache#atomic-locks]. Currently, those cache drivers include thememcached
,dynamodb
,redis
, anddatabase
drivers. In addition, you may not use thecookie
session driver.
Laravelはデフォルトで同じセッションを使用するリクエストを同時に実行できます。そのため、たとえばJavaScript HTTPライブラリを使用してアプリケーションに2つのHTTPリクエストを送信すると、両方が同時に実行されます。多くのアプリケーションでは、これは問題ではありません。ただし、セッションデータの損失は、両方がセッションにデータを書き込む2つの異なるアプリケーションエンドポイントに、同時要求を行うアプリケーションの小さなサブセットで発生する可能性があります。By default, Laravel allows requests using the same session to execute concurrently. So, for example, if you use a JavaScript HTTP library to make two HTTP requests to your application, they will both execute at the same time. For many applications, this is not a problem; however, session data loss can occur in a small subset of applications that make concurrent requests to two different application endpoints which both write data to the session.
これを軽減するために、Laravelでは特定のセッションの同時リクエストを制限できる機能を提供します。開始するには、block
メソッドをルート定義にチェーンするだけです。 この例では、/profile
エンドポイントの受信リクエストがセッションロックを取得します。このロックが保持されている間、同じセッションIDを共有する/profile
または/order
エンドポイントへの受信リクエストは、最初のリクエストの実行が完了するのを待ってから、実行を続行します。To mitigate this, Laravel provides functionality that allows you to limit concurrent requests for a given session. To get started, you may simply chain the block
method onto your route definition. In this example, an incoming request to the /profile
endpoint would acquire a session lock. While this lock is being held, any incoming requests to the /profile
or /order
endpoints which share the same session ID will wait for the first request to finish executing before continuing their execution:
Route::post('/profile', function () {
//
})->block($lockSeconds = 10, $waitSeconds = 10)
Route::post('/order', function () {
//
})->block($lockSeconds = 10, $waitSeconds = 10)
block
メソッドは2つのオプションの引数を取ります。block
メソッドの最初の引数は、セッションロックを解放する前に保持する最大秒数です。もちろん、リクエストがこの時間より前に実行終了した場合、ロックをより早く解放します。The block
method accepts two optional arguments. The first argument accepted by the block
method is the maximum number of seconds the session lock should be held for before it is released. Of course, if the request finishes executing before this time the lock will be released earlier.
block
メソッドの2番目の引数は、セッションロックを取得するときにリクエストが待つ秒数です。リクエストが指定秒数内にセッションロックを取得できない場合、Illuminate\Contracts\Cache\LockTimoutException
が投げられます。The second argument accepted by the block
method is the number of seconds a request should wait while attempting to obtain a session lock. A Illuminate\Contracts\Cache\LockTimoutException
will be thrown if the request is unable to obtain a session lock within the given number of seconds.
両引数のどちらも渡さない場合、ロックを最大10秒間取得し、リクエストはロックを取得するまで最大10秒間待ちます。If neither of these arguments are passed, the lock will be obtained for a maximum of 10 seconds and requests will wait a maximum of 10 seconds while attempting to obtain a lock:
Route::post('/profile', function () {
//
})->block()
カスタムセッションドライバの追加Adding Custom Session Drivers
ドライバの実装Implementing The Driver
カスタムセッションドライバでは、SessionHandlerInterface
を実装してください。このインターフェイスには実装する必要のある、シンプルなメソッドが数個含まれています。MongoDBの実装をスタブしてみると、次のようになります。Your custom session driver should implement the SessionHandlerInterface
. This interface contains just a few simple methods we need to implement. A stubbed MongoDB implementation looks something like this:
<?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
ファイルを設置しています。{tip} Laravel does not ship with a directory to contain your extensions. You are free to place them anywhere you like. In this example, we have created anExtensions
directory to house theMongoSessionHandler
.
これらのメソッドの目的を読んだだけでは理解しづらいため、それぞれのメソッドを簡単に見てみましょう。Since the purpose of these methods is not readily understandable, let's quickly cover what each of the methods do:
ドライバの登録Registering The Driver
ドライバを実装したら、フレームワークへ登録する準備が整いました。Laravelのセッションバックエンドへドライバを追加するには、Session
ファサードのextend
メソッドを呼び出します。サービスプロバイダのboot
メソッドから、extend
メソッドを呼び出してください。既存のAppServiceProvider
か真新しく作成し、呼び出してください。Once your driver has been implemented, you are ready to register it with the framework. To add additional drivers to Laravel's session backend, you may use the extend
method on the Session
facade[/docs/{{version}}/facades]. You should call the extend
method from the boot
method of a service provider[/docs/{{version}}/providers]. You may do this from the existing AppServiceProvider
or create an entirely new provider:
<?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 register()
{
//
}
/**
* 全アプリケーションサービスの初期起動
*
* @return void
*/
public function boot()
{
Session::extend('mongo', function ($app) {
// Return implementation of SessionHandlerInterface...
return new MongoSessionHandler;
});
}
}
セッションドライバを登録したら、config/session.php
設定ファイルでmongo
ドライバが使用できます。Once the session driver has been registered, you may use the mongo
driver in your config/session.php
configuration file.