# 服務 —— Session
## 1、簡介
由于HTTP。
### 1.1 配置
Session配置文件位于`config/session.php`。默認情況下,Laravel使用的`session`驅動為文件驅動,這對許多應用而言是沒有什么問題的。在生產環境中,你可能考慮使用`memcached`或者`redis`驅動以便獲取更快的session性能。
`session`驅動定義請求的session數據存放在哪里,Laravel可以處理多種類型的驅動:
* `file`?– session數據存儲在?`storage/framework/sessions`目錄下;
* `cookie`?– session數據存儲在經過加密的安全的cookie中;
* `database`?– session數據存儲在數據庫中
* `memcached`?/?`redis`?– session數據存儲在memcached/redis中;
* `array`?– session數據存儲在簡單PHP數組中,在多個請求之間是非持久化的。
> 注意:數組驅動通常用于運行測試以避免session數據持久化。
### 1.2 Session驅動預備知識
### 1.2.1 數據庫
當使用`database`session驅動時,需要設置表包含`session`項,下面是該數據表的表結構聲明:
~~~
Schema::create('sessions', function ($table) {
$table->string('id')->unique();
$table->text('payload');
$table->integer('last_activity');
});
~~~
你可以使用Artisan命令`session:table`來生成遷移:
~~~
php artisan session:table
composer dump-autoload
php artisan migrate
~~~
### 1.2.2?Redis
在Laravel中使用Redis?`session`驅動前,需要通過Composer安裝`predis/predis`包。
### 1.3 其它Session相關問題
Laravel框架內部使用`flash`?session鍵,所以你不應該通過該名稱添加數據項到session。
如果你需要所有存儲的session數據經過加密,在配置文件中設置`encrypt`配置為`true`。
## 2、基本使用
**訪問session**
首先,我們來訪問session,我們可以通過HTTP請求訪問session實例,可以在控制器方法中通過類型提示引入請求實例,記住,控制器方法依賴通過Laravel[服務容器](http://laravelacademy.org/post/93.html)注入:
~~~
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class UserController extends Controller{
/**
* 顯示指定用戶的屬性
*
* @param Request $request
* @param int $id
* @return Response
*/
public function showProfile(Request $request, $id)
{
$value = $request->session()->get('key');
//
}
}
~~~
從session中獲取數據的時候,還可以傳遞默認值作為第二個參數到`get`方法,默認值在指定鍵在session中不存在時返回。如果你傳遞一個閉包作為默認值到`get`方法,該閉包會執行并返回執行結果:
~~~
$value = $request->session()->get('key', 'default');
$value = $request->session()->get('key', function() {
return 'default';
});
~~~
如果你想要從session中獲取所有數據,可以使用`all`方法:
~~~
$data = $request->session()->all();
~~~
還可以使用全局的PHP函數`session`來獲取和存儲session中的數據:
~~~
Route::get('home', function () {
// 從session中獲取數據...
$value = session('key');
// 存儲數據到session...
session(['key' => 'value']);
});
~~~
**判斷session中是否存在指定項**
`has`方法可用于檢查數據項在session中是否存在。如果存在的話返回`true`:
~~~
if ($request->session()->has('users')) {
//
}
~~~
**在session中存儲數據**
獲取到session實例后,就可以調用多個方法來與底層數據進行交互,例如,`put`方法存儲新的數據到session中:
~~~
$request->session()->put('key', 'value');
~~~
**推送數據到數組session**
`push`?方法可用于推送數據到值為數組的session,例如,如果`user.teams`鍵包含團隊名數組,可以像這樣推送新值到該數組:
~~~
$request->session()->push('user.teams', 'developers');
~~~
**獲取并刪除數據**
`pull`方法將會從session獲取并刪除數據:
~~~
$value = $request->session()->pull('key', 'default');
~~~
**從session中刪除數據項**
`forget`方法從session中移除指定數據,如果你想要從session中移除所有數據,可以使用`flush`方法:
~~~
$request->session()->forget('key');
$request->session()->flush();
~~~
**重新生成Session ID**
如果你需要重新生成session ID,可以使用`regenerate`方法:
~~~
$request->session()->regenerate();
~~~
### 2.1 一次性數據
有時候你可能想要在session中存儲只在下個請求中有效的數據,可以通過`flash`方法來實現。使用該方法存儲的session數據只在隨后的HTTP請求中有效,然后將會被刪除:
~~~
$request->session()->flash('status', 'Task was successful!');
~~~
如果你需要在更多請求中保持該一次性數據,可以使用`reflash`方法,該方法將所有一次性數據保留到下一個請求,如果你只是想要保存特定一次性數據,可以使用`keep`方法:
~~~
$request->session()->reflash();
$request->session()->keep(['username', 'email']);
~~~
## 3、添加自定義Session驅動
要為Laravel后端session添加更多驅動,可以使用Session門面上的`extend`方法。可以在[服務提供者](http://laravelacademy.org/post/91.html)的`boot`方法中調用該方法:
~~~
<?php
namespace App\Providers;
use Session;
use App\Extensions\MongoSessionStore;
use Illuminate\Support\ServiceProvider;
class SessionServiceProvider extends ServiceProvider{
/**
* Perform post-registration booting of services.
*
* @return void
*/
public function boot()
{
Session::extend('mongo', function($app) {
// Return implementation of SessionHandlerInterface...
return new MongoSessionStore;
});
}
/**
* Register bindings in the container.
*
* @return void
*/
public function register()
{
//
}
}
~~~
需要注意的是自定義session驅動需要實現`SessionHandlerInterface`接口,該接口包含少許我們需要實現的方法,一個MongoDB的實現如下:
~~~
<?php
namespace App\Extensions;
class MongoHandler 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) {}
}
~~~
由于這些方法并不像緩存的`StoreInterface`接口方法那樣容易理解,我們接下來快速過一遍每一個方法:
* `open`?方法用于基于文件的session存儲系統,由于Laravel已經有了一個?`file`?session 驅動,所以在該方法中不需要放置任何代碼,可以將其置為空方法。
* `close`?方法和`open`?方法一樣,也可以被忽略,對大多數驅動而言都用不到該方法。
* `read`?方法應該返回與給定$sessionId?相匹配的session數據的字符串版本,從驅動中獲取或存儲session數據不需要做任何序列化或其它編碼,因為Laravel已經為我們做了序列化。
* `write`?方法應該講給定`$data`?寫到持久化存儲系統相應的`$sessionId`?, 例如MongoDB, Dynamo等等。
* `destroy`?方法從持久化存儲中移除?`$sessionId`?對應的數據。
* `gc`?方法銷毀大于給定$lifetime?的所有?session數據,對本身擁有過期機制的系統如?Memcached?和Redis而言,該方法可以留空。
session驅動被注冊之后,就可以在配置文件`config/session.php`中使用`mongo`?驅動了。
- 前言
- 序言
- 序言 ―― 發行版本說明
- 序言 ―― 升級指南
- 序言 ―― 貢獻代碼
- 開始
- 開始 ―― 安裝及配置
- 開始 ―― Laravel Homestead
- 基礎
- 基礎 ―― HTTP路由
- 基礎 ―― HTTP 中間件
- 基礎 ―― HTTP 控制器
- 基礎 ―― HTTP 請求
- 基礎 ―― HTTP 響應
- 基礎 ―― 視圖
- 基礎 ―― Blade模板
- 架構
- 架構 ―― 一次請求的生命周期
- 架構 ―― 應用目錄結構
- 架構 ―― 服務提供者
- 架構 ―― 服務容器
- 架構 ―― 契約
- 架構 ―― 門面
- 數據庫
- 數據庫 ―― 起步
- 數據庫 ―― 查詢構建器
- 數據庫 ―― 遷移
- 數據庫 ―― 填充數據
- Eloquent ORM
- Eloquent ORM ―― 起步
- Eloquent ORM ―― 關聯關系
- Eloquent ORM ―― 集合
- Eloquent ORM ―― 調整器
- Eloquent ORM ―― 序列化
- 服務
- 服務 ―― 用戶認證
- 服務 ―― Artisan 控制臺
- 服務 ―― Laravel Cashier(交易)
- 服務 ―― 緩存
- 服務 ―― 集合
- 服務 ―― Laravel Elixir
- 服務 ―― 加密
- 服務 ―― 錯誤&日志
- 服務 ―― 事件
- 服務 ―― 文件系統/云存儲
- 服務 ―― 哈希
- 服務 ―― 幫助函數
- 服務 ―― 本地化
- 服務 ―― 郵件
- 服務 ―― 包開發
- 服務 ―― 分頁
- 服務 ―― 隊列
- 服務 ―― Redis
- 服務 ―― Session
- 服務 ―― Envoy 任務運行器(SSH任務)
- 服務 ―― 任務調度
- 服務 ―― 測試
- 服務 ―― 驗證