laravel 基礎(chǔ)教程 —— Session

Session

簡(jiǎn)介

由于 HTTP 驅(qū)動(dòng)是一種無(wú)狀態(tài)的協(xié)議鲜戒,這通常意味著服務(wù)端并不能清楚的知道當(dāng)前請(qǐng)求用戶(hù)與之前請(qǐng)求用戶(hù)間的關(guān)系赁炎,而 Session 提供了這種跨請(qǐng)求用戶(hù)的解決方案诵姜。Laravel 附帶了簡(jiǎn)潔統(tǒng)一的 API 來(lái)支持各種后端 session 驅(qū)動(dòng)蚊俺。對(duì)于 Memcached圈纺,Redis 和數(shù)據(jù)庫(kù)這種流行的后端驅(qū)動(dòng)了讨,Laravel 提供了開(kāi)箱即用的支持。

配置

session 的配置文件被存儲(chǔ)在 config/session.php钧排。你應(yīng)該確保在使用前閱讀該文件中的配置項(xiàng)注釋敦腔。Laravel 對(duì)配置中的每一項(xiàng)都進(jìn)行了詳細(xì)的注釋。默認(rèn)的恨溜,laravel 配置使用的是 file session 驅(qū)動(dòng)符衔,這對(duì)于大多數(shù)應(yīng)用來(lái)說(shuō)已經(jīng)夠用了找前。但是在生產(chǎn)環(huán)境中還是建議使用 memcached 或者 redis 這種內(nèi)存級(jí)驅(qū)動(dòng),這對(duì)于應(yīng)用的 session 性能來(lái)說(shuō)會(huì)是一個(gè)很大的提升判族。

對(duì)于每個(gè)請(qǐng)求的 session 數(shù)據(jù)躺盛,都會(huì)存儲(chǔ)在你所定義的 session driver 所在的位置中。下列驅(qū)動(dòng)在 laravel 中可以開(kāi)箱即用:

  • file - sessions 會(huì)存儲(chǔ)在 storage/framework/sessions 中形帮。
  • cookie - sessions 會(huì)被存儲(chǔ)在經(jīng)過(guò)安全加密的 cookies 中槽惫。
  • database - sessions 會(huì)被存儲(chǔ)在你應(yīng)用中所使用的數(shù)據(jù)庫(kù)中。
  • memcached / redis - sessions 會(huì)被存儲(chǔ)在更快的內(nèi)存級(jí)存儲(chǔ)驅(qū)動(dòng)中辩撑。
  • array - sessions 會(huì)使簡(jiǎn)單存儲(chǔ)在 PHP 的數(shù)組中躯枢,并且它不能被跨請(qǐng)求訪(fǎng)問(wèn)。

注意:array 驅(qū)動(dòng)通常是用來(lái)進(jìn)行測(cè)試時(shí)使用的以避免持久的 session 數(shù)據(jù)槐臀。

驅(qū)動(dòng)先決條件

數(shù)據(jù)庫(kù)

當(dāng)使用 database session 驅(qū)動(dòng)時(shí)锄蹂,你需要先創(chuàng)建一個(gè)表來(lái)存儲(chǔ) session 項(xiàng)。下面的例子是數(shù)據(jù)庫(kù) session 驅(qū)動(dòng)表的架構(gòu)聲明:

Schema::create('sessions', function ($table) {
  $table->string('id')->unique();
  $table->integer('user_id')->nullable();
  $table->string('ip_address', 45)->nullable();
  $table->text('user_agent')->nullable();
  $table->text('payload');
  $table->integer('last_activity');
});

你也可以使用 session:table Artisan 命令來(lái)生成一個(gè)數(shù)據(jù)庫(kù)會(huì)話(huà)驅(qū)動(dòng)的遷移表:

php artisan session:table

composer dump-autoload

php artisan migrate

Redis

在使用 Redis session 驅(qū)動(dòng)之前水慨,你需要通過(guò) Composer 安裝 predis/predis(~1.0)得糜。

其他 Session 注意事項(xiàng)

Laravel 框架內(nèi)部使用了 flash 作為 session 其中的一個(gè)鍵,所以你應(yīng)該避免使用該名稱(chēng)的鍵到 session 中晰洒。

如果你需要存儲(chǔ)安全加密后的 session 數(shù)據(jù)朝抖,你可以在配置文件中將 encrypt 選項(xiàng)設(shè)置為 true

基礎(chǔ)用法

訪(fǎng)問(wèn) Session

首先谍珊,讓我們來(lái)訪(fǎng)問(wèn) session治宣。我們可以通過(guò) HTTP 請(qǐng)求來(lái)訪(fǎng)問(wèn) session 的實(shí)例。HTTP 請(qǐng)求可以通過(guò)在控制器方法中使用類(lèi)型提示來(lái)進(jìn)行依賴(lài)注入砌滞。你應(yīng)該記得侮邀,控制器方法的依賴(lài)會(huì)通過(guò) laravel 的服務(wù)容器進(jìn)行注入:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class UserController extends Controller
{
  /**
   * Show the profile for the given user.
   *
   * @param Request $request
   * @param int $id
   * @return Response
   */
   public function showProfile(Request $request, $id)
   {
     $value = $request->session()->get('key');

     //
   }
}

當(dāng)你從 session 中檢索值時(shí),你也可以指定一個(gè)默認(rèn)的值到 get 方法的第二個(gè)參數(shù)贝润,默認(rèn)值會(huì)在 session 未檢索到相應(yīng)鍵的值時(shí)返回绊茧。你也可以傳遞 Closure 作為默認(rèn)值,如果找不到相應(yīng)的鍵打掘,Closure 執(zhí)行的結(jié)果所返回的值將作為默認(rèn)值:

$value = $request->session()->get('key', 'default');

$value = $request->session()->get('key', function () {
  return 'default'; 
});

如果你希望從 session 中檢索出所有的值华畏,你可以使用 all 方法:

$data = $request->session()->all();

你可以可以使用全局幫助方法 session 來(lái)進(jìn)行值的檢索和存儲(chǔ):

Route::get('home', function () {
  // Retrieve a piece of data from the session...
  $value = session('key');

  // Store a piece of data in the session...
  session(['key' => 'value']);
});

判斷 session 是否存在某項(xiàng)

你可以使用 has 方法來(lái)判斷 session 中是否含有某項(xiàng),如果存在則返回 true:

if ($request->session()->has('user')) {
  //
}

在 session 中存儲(chǔ)數(shù)據(jù)

一旦你獲取了 session 的實(shí)例尊蚁,你就擁有了和底層數(shù)據(jù)進(jìn)行交互的能力亡笑,你可以通過(guò)各種實(shí)例的方法來(lái)進(jìn)行交互。比如横朋,你可以使用 put 方法來(lái)在 session 中存儲(chǔ)一個(gè)新的數(shù)據(jù)項(xiàng):

$request->session()->put('key', 'value');

推送內(nèi)容到 session 中值為數(shù)組的項(xiàng)

你可以使用 push 方法來(lái)將一個(gè)新的值推送到 session 中值為數(shù)組的項(xiàng)中仑乌。比如,如果 user.teams 鍵表明了數(shù)組在 session 中的路徑,你可以像這樣推送新的值到該數(shù)組中:

$request->session()->push('user.teams', 'developers');

檢索并刪除某項(xiàng)

pull 方法會(huì)在檢索的同時(shí)在 session 中刪除該項(xiàng):

$value = $request->session()->pull('key', 'default');

刪除 session 中的某項(xiàng)

你可以使用 forget 方法來(lái)刪除 session 中的某一項(xiàng)數(shù)據(jù)绝骚,如果你想要移除 session 中的所有數(shù)據(jù),你可以使用 flush 方法:

$request->session()->forget('key');

$request->session()->flush();

重新生成 session ID

如果你需要重新生成 session ID祠够,你可以使用 regenerate 方法:

$request->session()->regenerate();

閃存數(shù)據(jù)

有時(shí)候你希望在 session 中存儲(chǔ)某些數(shù)據(jù)压汪,但是只允許下一次請(qǐng)求時(shí)使用,使用后即消除古瓤。那么就可以使用 flash 方法止剖。這方法在 session 中存儲(chǔ)的數(shù)據(jù)只能在隨后的請(qǐng)求中進(jìn)行訪(fǎng)問(wèn),并且在之后刪除落君。閃存的數(shù)據(jù)通常用來(lái)做一些臨時(shí)的狀態(tài)消息:

$request->session()->flash('status', 'Task was successful!');

如果你需要維持閃存的數(shù)據(jù)到更多的請(qǐng)求穿香,你可以使用 reflash 方法,它會(huì)維持所有的閃存數(shù)據(jù)到額外的請(qǐng)求中绎速。如果你只需要維持指定的閃存數(shù)據(jù)皮获,你可以使用 keep 方法:

$request->session()->reflash();

$request->session()->keep(['username', 'email']);

添加自定義的 Session 驅(qū)動(dòng)

你需要使用 Session 假面的 extend 方法才能添加額外的 session 驅(qū)動(dòng)到 Laravel 中。你可以在服務(wù)提供者的 boot 方法中來(lái)調(diào)用 extend 方法:

<?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()
    {
      //
    }
}

你應(yīng)該注意你的自定義 session 驅(qū)動(dòng)應(yīng)該實(shí)現(xiàn) SessionHandlerInterface 接口纹冤。該接口僅包含了幾個(gè)簡(jiǎn)單的需要實(shí)現(xiàn)的方法洒宝。一個(gè)實(shí)現(xiàn)了的 MongoDB 驅(qū)動(dòng)的結(jié)構(gòu)應(yīng)該像下面一樣:

<?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 那樣難于理解。所以萌京,我們就來(lái)快速的過(guò)一下吧:

  • open 方法一般用于基于文件的 session 存儲(chǔ)系統(tǒng)雁歌。由于 laravel 已經(jīng)附帶了 file session 驅(qū)動(dòng),所以你幾乎不需要在這個(gè)方法中添加任何的代碼知残。你可以直接放置其為空方法靠瞎。事實(shí)上,這是一種可憐的接口設(shè)計(jì)(我們將會(huì)在后面討論它)求妹,PHP 必須要我們實(shí)現(xiàn)這個(gè)方法乏盐。
  • close 方法,類(lèi)似于 open 方法制恍,你也可以對(duì)其進(jìn)行忽視丑勤,對(duì)于大多數(shù)驅(qū)動(dòng)來(lái)說(shuō)根本不需要。
  • read 方法應(yīng)該根據(jù)給定的 $sessionId 返回 session 中關(guān)聯(lián)數(shù)據(jù)的字符串版本吧趣。你不需要在存儲(chǔ)或檢索時(shí)做任何的序列化或其它的編碼操作法竞,因?yàn)?laravel 會(huì)為你執(zhí)行序列化服務(wù)。
  • destroy 方法應(yīng)該從 session 存儲(chǔ)中刪除所關(guān)聯(lián)的數(shù)據(jù)强挫。
  • gc 方法應(yīng)該根據(jù)給定的 $lifetime UNIX 時(shí)間戳刪除 session 所關(guān)聯(lián)的過(guò)期數(shù)據(jù)岔霸。對(duì)于擁有自動(dòng)過(guò)期能力的系統(tǒng),比如 Memcached 和 Redis俯渤,你可以直接讓這個(gè)方法為空呆细。

一旦你的 session 驅(qū)動(dòng)被注冊(cè)。你就可以在 config/session.php 配置文件中使用 mongo 驅(qū)動(dòng)了八匠。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末絮爷,一起剝皮案震驚了整個(gè)濱河市趴酣,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌坑夯,老刑警劉巖岖寞,帶你破解...
    沈念sama閱讀 222,000評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異柜蜈,居然都是意外死亡仗谆,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)淑履,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)隶垮,“玉大人,你說(shuō)我怎么就攤上這事秘噪±晖蹋” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,561評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵指煎,是天一觀(guān)的道長(zhǎng)捷绒。 經(jīng)常有香客問(wèn)我,道長(zhǎng)贯要,這世上最難降的妖魔是什么暖侨? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,782評(píng)論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮崇渗,結(jié)果婚禮上字逗,老公的妹妹穿的比我還像新娘。我一直安慰自己宅广,他們只是感情好葫掉,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著跟狱,像睡著了一般俭厚。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上驶臊,一...
    開(kāi)封第一講書(shū)人閱讀 52,394評(píng)論 1 310
  • 那天挪挤,我揣著相機(jī)與錄音,去河邊找鬼关翎。 笑死扛门,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的纵寝。 我是一名探鬼主播论寨,決...
    沈念sama閱讀 40,952評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了葬凳?” 一聲冷哼從身側(cè)響起绰垂,我...
    開(kāi)封第一講書(shū)人閱讀 39,852評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎火焰,沒(méi)想到半個(gè)月后劲装,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,409評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡荐健,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評(píng)論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了琳袄。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片江场。...
    茶點(diǎn)故事閱讀 40,615評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖窖逗,靈堂內(nèi)的尸體忽然破棺而出址否,到底是詐尸還是另有隱情,我是刑警寧澤碎紊,帶...
    沈念sama閱讀 36,303評(píng)論 5 350
  • 正文 年R本政府宣布佑附,位于F島的核電站,受9級(jí)特大地震影響仗考,放射性物質(zhì)發(fā)生泄漏音同。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評(píng)論 3 334
  • 文/蒙蒙 一秃嗜、第九天 我趴在偏房一處隱蔽的房頂上張望权均。 院中可真熱鬧,春花似錦锅锨、人聲如沸叽赊。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,470評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)必指。三九已至,卻和暖如春恕洲,著一層夾襖步出監(jiān)牢的瞬間塔橡,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,571評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工霜第, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留谱邪,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,041評(píng)論 3 377
  • 正文 我出身青樓庶诡,卻偏偏與公主長(zhǎng)得像惦银,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容