【Laravel】Sessionの扱い方ざっくりまとめ

# 前提

## HTTP通信はステートレス

- HTTP通信単体では「状態」を持てません（これを **ステートレス** と呼びます）
- 「ログイン状態」や、「カートに商品をいれた状態」を保ちたい場合、その **「状態」をキープするための仕組み** が必要です
- それが **セッション管理** という仕組みです

## セッション管理＝クッキー＋データベース

- 「一定期間に行う一連の処理」をセッションと呼びます
- セッション管理は、サーバが **セッションID（ランダムな文字列）** をクライアントに付与し、 **サーバ側がIDを毎回照合・IDに紐づく情報を取得する** ことで状態を保持します
- 具体的には、
    -  **クッキー（クライアント側にIDを保存）** と、
    -  **データベース（サーバ側にID＆保持したい情報を保存）** を使用することが多いです
- 他にも方法はありますが、いずれもセキュリティを考慮する必要があります

## クッキー

- 主にサーバから付与され、ブラウザに保存される文字列データです
- HTTP通信のレスポンスヘッダ（Set-Cookie）を通して付与されます
- 保存形式は、 **キー名＝値** （＋更新日時）
- サーバにアクセスする際、自動送信されます（HTTP通信のリクエストヘッダ）
    - もちろん、他のサーバへは送信しません（セキュリティ）

# Laravelのセッション管理について

## セッションの設定方法

- セッションの設定は`config/session.php`ファイルで行います

```php
<?php
return [
    'driver' => env('SESSION_DRIVER', 'file'), // Sessionの保存方法
    'lifetime' => 120, // Cookie（Session）の有効期限（分, 120 = 2時間）
    'expire_on_close' => false, // 有効期限を「ブラウザのタブを閉じるまで」に設定
    'encrypt' => true, // Cookieの暗号化

		// 保存先の設定
    'files' => storage_path('framework/sessions'), // （fileに保存する場合）保存先パス
    'connection' => null, // （database,redisに保存する場合）接続先
    'table' => 'sessions', // (databaseに保存する場合）保存先テーブル
    'store' => null, // （apc,memcashedに保存する場合）キャッシュストア

    'lottery' => [2, 100], // ガベージコレクションの発生確率（2/100 = 2%）
    'cookie' => 'laravel_session', // Cookieのキー名
    'path' => '/', // 有効なパス（'/' = サイト全体）
    'domain' => env('SESSION_DOMAIN', null), // 有効なドメイン
    'secure' => env('SESSION_SECURE_COOKIE', false), // 暗号化通信の要否
    'http_only' => true, // HTTP経由でのみアクセス（JavaScript経由ではアクセス不可）
];
```

[Laravel 8.x HTTPセッション](https://readouble.com/laravel/8.x/ja/session.html)

## env関数とenvファイル

- `env()`では、プロジェクトフォルダ下の`.envファイル`で設定された環境変数を取得しています
    - 第一引数の値がなければ、第二引数の値（デフォルト値）を返します
- envファイルの変更を反映させるには、以下のコマンドを使用します

```php
php artisan config:clear
```

## driver（Sessionの保存方法）

サーバ側は情報をデータベース保存する…と書きましたが、実際にはデータベース以外も利用可能です

- `file`：　`storage/framework/sessions`に保存（デフォルトの保存方法）
- `cookie`：　暗号化したクッキーに保存
- `database`：　RDBに保存、テーブルを作成する必要がある
- `memcashed`/`redis`：　キャッシュベースの保存域へ保存（👈高速なのでオススメ）
- `dynamodb`：　AWS DynamoDBへ保存
- `array`：　PHP配列に保存（永続化しない）

# Sessionデータの使い方

## Sessionデータへのアクセス方法

- Laravelでは３通りのアクセス方法があります

### 1. Requestインスタンス（`Request $request`）

```php
$request->session()->hoge()
```

### 2. グローバルSessionヘルパ

```php
session()->hoge()
```

### 3. Sessionファサード

```php
Session::hoge()
```

## データをセットする

```php
// Controller
public function sample(Request $request)
{
		$request->session()->put('キー名', 値); // sessionデータをセット
		return view('sample');
}
```

```php
// 複数のデータを保存
$request->session()->put(['key1'=> value1, 'key2'=> value2, ...);

// フラッシュデータを保存
$request->session()->flash('キー名', 値);
// => 直後のリクエストでのみ利用可能、その後削除される

// 指定したデータを削除
$request->session()->forget('キー名');

// セッションのすべてのデータを削除
$request->session()->flush();

```

## データを取得する

```php
// Controller
public function sample(Request $request)
{
		$value = $request->session()->get('キー名'); // sessionデータから値を取得
		return view('sample');
}
```

```php
// get()は第二引数にデフォルト値を指定できる
$value = $request->session()->get('キー名', 'デフォルト値');

// 指定したデータを取得後に削除
$value = $request->session()->pull('キー名', 'デフォルト値');

// セッションの全データを取得
$items = $request->session()->all();

// セッションに指定したキーが存在するか調べる
if ($request->session()->exists('キー名')){
	// 処理
}

// 値が存在するか（null以外か）調べる
if ($request->session()->has('キー名')){
	// 処理
}
```

## その他

```php
// セッションIDの再発行
$request->session()->regenerate();

// セッションIDを再生成し、セッションからすべてのデータを削除
$request->session()->invalidate();
```

# 参考
[Cookieとセッションをちゃんと理解する - Qiita](https://qiita.com/hththt/items/07136ad74127999df271)

[CookieとWebStorageとSessionについてのまとめ - Qiita](https://qiita.com/pipiox/items/95554673ba3b078ac112)

[PHPフレームワークLaravel Webアプリケーション開発 バージョン8.x対応](https://www.amazon.co.jp/dp/B096ZSB658/ref=cm_sw_r_tw_dp_2T2RJ8AV5WK1WKDMNB4M)

[独習PHP 第4版](https://www.amazon.co.jp/dp/B09372PSG7/ref=cm_sw_r_tw_dp_QWE04QDD4ZFT9Z9NQP7T)