# Introduction
學習一個框架, Ray 的想法是, 在深入理解底層實作的原理之前, 應該先知道這個框架的 使用方法
; 先學習怎麼使用這個前人造的輪子, 再學習怎麼樣造一個輪子。
所以本篇文章重點在於細讀官方文件, 並將內容理解後以 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, 若超過將會 throwIlluminate\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
留言