# 版本
# 前言
我喜歡使用 Laravel 開發的感覺, 除了開發快速, 程式碼簡潔且優雅之外, Laravel 框架本身也是一個很好的學習參照物。 本篇主要將官方文件重點整理成 Q&A 的形式呈現, 原子化的概念, 這方式並不適用於每個人, 但若對你有幫助, 我會很開心。
# 目錄
# Configuration
Laravel 中, 如果我前面有掛 Load Balancer, 那我 session 要用什麼方式儲存?
centralized store, 像是 database, redis
Laravel 中, 支援哪幾種 session driver?
file, cookie, database, memcached / redis, dynamodb, array
Laravel 中, session driver array 主要用於哪裡?
主要用於 testing, 避免 session 持有化數據
# Driver Prerequisites
# Database
以下的 Laravel example code 的意思是?
- Example:
<?php
Schema::create('sessions', function ($table) {
$table->string('id')->primary();
$table->foreignId('user_id')->nullable()->index();
$table->string('ip_address', 45)->nullable();
$table->text('user_agent')->nullable();
$table->text('payload');
$table->integer('last_activity')->index();
});
- Answer: 當 session driver 使用 database 時, 需建立一張 table 來存放 session records
以下的 Laravel example code 的意思是?
- Example:
<?php
php artisan session:table
php artisan migrate
- Answer: 當 session driver 使用 database 時, 可使用 CLI 建立存放 session records 的 table
# Interacting With The Session
# Retrieving Data
以下的 Laravel example code 的意思是?
- Example:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class UserController extends Controller
{
public function show(Request $request, $id)
{
$value = $request->session()->get('key');
//
}
}
- Answer: 透過 $request 取得 session
'key'
的 value
以下的 Laravel example code 的意思是?
- Example:
<?php
$value = $request->session()->get('key', 'default');
$value = $request->session()->get('key', function () {
return 'default';
});
- Answer: 從 $request 取得 session
'key'
的 value, 若'key'
不可得, 則 return arg2 的 default 值, 或執行 arg2 closure, 取得 closure return 的值
# The Global Session Helper
以下的 Laravel example code 的意思是?
- Example:
<?php
Route::get('/home', function () {
$value = session('key');
$value = session('key', 'default');
session(['key' => 'value']);
});
- Answer: 使用 session global helper 從 session 中取得 key 為
'key'
的 value 從 session 中取得 key 為'key'
的 value, 若'key'
不可得, return'default'
將['key' => 'value']
存到 session 中
# Retrieving All Session Data
以下的 Laravel example code 的意思是?
- Example:
<?php
$data = $request->session()->all();
- Answer: 取得 session 中的所有資料
# Determining If An Item Exists In The Session
以下的 Laravel example code 的意思是?
- Example:
<?php
if ($request->session()->has('users')) {
//
}
- Answer: 判斷 session 中是否有 key 為
'users'
, 且 value 不為 null
以下的 Laravel example code 的意思是?
- Example:
<?php
if ($request->session()->exists('users')) {
//
}
- Answer: 判斷 session 是否有 key 為
'users'
, value 允許為 null
# Storing Data
以下的 Laravel example code 的意思是?
- Example:
<?php
$request->session()->put('key', 'value');
session(['key' => 'value']);
- Answer: 使用 $request 或 session global helper 將
['key' => 'value']
存到 session
# Pushing To Array Session Values
以下的 Laravel example code 的意思是?
- Example:
<?php
$request->session()->push('user.teams', 'developers');
- Answer: 使用在當要把 item push 到一個 session value 中, 而該 value 是一個 array 將
'developers'
push 到 session 中的 user.teams, teams 為一個 array
# Retrieving & Deleting An Item
以下的 Laravel example code 的意思是?
- Example:
<?php
$value = $request->session()->pull('key', 'default');
- Answer: 從 session 中取得並刪除該 record, 若不可能, return arg2 的
'default'
# Flash Data
以下的 Laravel example code 的意思是?
- Example:
<?php
$request->session()->flash('status', 'Task was successful!');
- Answer: 使用 flash() 將
['status' => 'Task was successful!']
存到 session, 並且可用在下一個 request, 在下一個 request 之後便會自動刪除
以下的 Laravel example code 的意思是?
- Example:
<?php
$request->session()->reflash();
$request->session()->keep(['username', 'email']);
- Answer: 預設使用 flash() 儲存的 session 在下一個 request 之後便會自動刪除 使用 refresh() 可以延長保存期限, 多一個 request 使用 keep() 同上, 但只針對特定的
key
延長期限
# Deleting Data
以下的 Laravel example code 的意思是?
- Example:
<?php
$request->session()->forget('name');
$request->session()->forget(['name', 'status']);
$request->session()->flush();
- Answer: 使用 forget() 從 session 當中移除指定的 key 使用 flush() 會將 session 中資料完全移除
# Regenerating The Session ID
以下的 Laravel example code 的意思是?
- Example:
<?php
$request->session()->regenerate();
- Answer: 若使用 Laravel 預設的驗證, 像是 application starter kits 或是 Laravel Fortify, 預設 authenticate user 都會重新產生 session ID 然而, 也可手動重新產生
# Session Blocking
若要使用 Laravel Session Blocking, 支援哪幾種 session driver?
memcached, dynamodb, redis, database
以下的 Laravel example code 的意思是?
- Example:
<?php
Route::post('/profile', function () {
//
})->block($lockSeconds = 10, $waitSeconds = 10)
Route::post('/order', function () {
//
})->block($lockSeconds = 10, $waitSeconds = 10)
- Answer: 使用 Session Block Laravel 預設允許同時間處理兩個以上帶有相同 session 的 request, 然而, 在少數的情況下可能會有 session 資料丟失的問題, 比方說, 當 request 同時發向同一個 application 兩個不同的 endpoints, 而這兩個不同的 endpoints 會對 session 進行修改 可使用 block() 避免這個問題, 當使用 block() 時, 在當前 request 完成之前, 該 session 會被 lock 住, 直到該 request 完成後, 才允許相同 session 的下一個 request arg1 表示 lock 的時間, 如果 request 完成會自動 release arg2 表示新的 request 要嘗試多久來取得新的 session lock, 若超過將會 throw
Illuminate\Contracts\Cache\LockTimeoutException
兩個 args 預設都是 10 秒
# Adding Custom Session Drivers
# Implementing The Driver
以下的 Laravel example code 的意思是?
- Example:
<?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) {}
}
- Answer: 若要自定義 Session Driver, 可在
App\Extensions
folder 建立一個 class, 並 implementSessionHandlerInterface
, 實作這些 method
以下的 Laravel example code 的意思是?
- Example:
<?php
namespace App\Extensions;
class MongoSessionHandler implements \SessionHandlerInterface
{
public function open($savePath, $sessionName) {}
}
- Answer: 用在 file based session store system, 因為 Laravel 已經有內建的 file session driver, 所以若要自定義 session driver, 這個 method 可以留空
以下的 Laravel example code 的意思是?
- Example:
<?php
namespace App\Extensions;
class MongoSessionHandler implements \SessionHandlerInterface
{
public function close() {}
}
- Answer: 用在 file based session store system, 因為 Laravel 已經有內建的 file session driver, 所以若要自定義 session driver, 這個 method 可以留空
以下的 Laravel example code 的意思是?
- Example:
<?php
namespace App\Extensions;
class MongoSessionHandler implements \SessionHandlerInterface
{
public function read($sessionId) {}
}
- Answer: 當自定義 session driver 時需 implement 的 method read() 需 return session data 的 string version 不需要做任何 serialization, 因為 Laravel 預設做完了
以下的 Laravel example code 的意思是?
- Example:
<?php
namespace App\Extensions;
class MongoSessionHandler implements \SessionHandlerInterface
{
public function write($sessionId, $data) {}
}
- Answer: 當自定義 session driver 時需 implement 的 method write() 需將與
$sessionId
相關的$data
string 寫到自定義的 storage 中 不需要做任何 serialization, 因為 Laravel 預設做完了
以下的 Laravel example code 的意思是?
- Example:
<?php
namespace App\Extensions;
class MongoSessionHandler implements \SessionHandlerInterface
{
public function destroy($sessionId) {}
}
- Answer: 當自定義 session driver 時需 implement 的 method destroy() 需將與
$sessionId
有關的 data 從 storage 中移除
以下的 Laravel example code 的意思是?
- Example:
<?php
namespace App\Extensions;
class MongoSessionHandler implements \SessionHandlerInterface
{
public function gc($lifetime) {}
}
- Answer: 當自定義 session driver 時需 implement 的 method gc() 需將比
$lifetime
還舊的檔案從 storage 中清掉, 格式為UNIX timestamp
如果是使用self-expiring
系統, 像是 Memcached 或 Redis, 此 method 可留空
# Registering The Driver
以下的 Laravel example code 的意思是?
- Example:
<?php
<?php
namespace App\Providers;
use App\Extensions\MongoSessionHandler;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\ServiceProvider;
class SessionServiceProvider extends ServiceProvider
{
public function register()
{
//
}
public function boot()
{
Session::extend('mongo', function ($app) {
// Return an implementation of SessionHandlerInterface...
return new MongoSessionHandler;
});
}
}
- Answer: 當完成自定義的 session driver implementation class 之後, 可在 SessionServiceProvider 的 boot method 中, 使用 Session::extend() 來註冊新的 session driver, mongo 為 session driver 的名稱, closure 會 return implementation class 註冊完成後, 就可以在
config/session.php
使用mongo
session driver