摘要:我們?cè)谶@個(gè)類中的方法看到如下代碼,一個(gè)典型的過濾器,在這個(gè)中獲取的方法是。,整個(gè)初始化的過程總結(jié)下巧妙的使用了面向?qū)ο蟮慕涌诜绞剑瑸槲覀兲峁┝烁鞣N各樣不同的存儲(chǔ)方式,一旦我們了解了存儲(chǔ)方式和加密規(guī)則,讓不同的容器進(jìn)行共享的目的也可以達(dá)到
前些天,為了解答一個(gè)問題,就去研究了Laravel的源碼,講講我的收獲:
這個(gè)是問題源:
http://segmentfault.com/q/1010000003776645?_ea=365137
本文講的Laravel全部使用5.1版本。
我們首先看Laravel是如何創(chuàng)建Session組件的。
首先我們可以看見在Kernel.php中注冊(cè)了StartSession這個(gè)類(這里不去討論Laravel的DI和IoC),看下這個(gè)類是如何使用的。
我們?cè)谶@個(gè)類中的handle方法看到如下代碼
public function handle($request, Closure $next) { $this->sessionHandled = true; // If a session driver has been configured, we will need to start the session here // so that the data is ready for an application. Note that the Laravel sessions // do not make use of PHP "native" sessions in any way since they are crappy. if ($this->sessionConfigured()) { $session = $this->startSession($request); $request->setSession($session); } $response = $next($request); // Again, if the session has been configured we will need to close out the session // so that the attributes may be persisted to some storage medium. We will also // add the session identifier cookie to the application response headers now. if ($this->sessionConfigured()) { $this->storeCurrentUrl($request, $session); $this->collectGarbage($session); $this->addCookieToResponse($response, $session); } return $response; }
OK,一個(gè)典型的過濾器,在這個(gè)StartSession中獲取Session的方法是getSession。
Get Session它使用了Laravel注入的SessionManager 這個(gè)類的完整限定名是:IlluminateSessionSessionManager
/** * Start the session for the given request. * * @param IlluminateHttpRequest $request * @return IlluminateSessionSessionInterface */ protected function startSession(Request $request) { with($session = $this->getSession($request))->setRequestOnHandler($request); $session->start(); return $session; } /** * Get the session implementation from the manager. * * @param IlluminateHttpRequest $request * @return IlluminateSessionSessionInterface */ public function getSession(Request $request) { $session = $this->manager->driver(); $session->setId($request->cookies->get($session->getName())); return $session; }
我們?cè)谶@個(gè)函數(shù)中看到,它調(diào)用了SessionManager的drive方法,drive方法是SessionManager的父類Manager中定義的,看到它的實(shí)現(xiàn)是這樣的
/** * Get a driver instance. * * @param string $driver * @return mixed */ public function driver($driver = null) { $driver = $driver ?: $this->getDefaultDriver(); // If the given driver has not been created before, we will create the instances // here and cache it so we can return it next time very quickly. If there is // already a driver created by this name, we"ll just return that instance. if (! isset($this->drivers[$driver])) { $this->drivers[$driver] = $this->createDriver($driver); } return $this->drivers[$driver]; } /** * Create a new driver instance. * * @param string $driver * @return mixed * * @throws InvalidArgumentException */ protected function createDriver($driver) { $method = "create".ucfirst($driver)."Driver"; // We"ll check to see if a creator method exists for the given driver. If not we // will check for a custom driver creator, which allows developers to create // drivers using their own customized driver creator Closure to create it. if (isset($this->customCreators[$driver])) { return $this->callCustomCreator($driver); } elseif (method_exists($this, $method)) { return $this->$method(); } throw new InvalidArgumentException("Driver [$driver] not supported."); }
也就是調(diào)用getDefaultDriver方法
/** * Get the default session driver name. * * @return string */ public function getDefaultDriver() { return $this->app["config"]["session.driver"]; }
這里就是我們?cè)?b>app/config/session.php中定義的driver字段,獲取這個(gè)字段后,我們可以從createDriver的源碼看到,它實(shí)際上是調(diào)用createXXXXDriver的方式獲取到driver的。
OK,我們看下最簡單的File,也就是createFileDriver
/** * Create an instance of the file session driver. * * @return IlluminateSessionStore */ protected function createFileDriver() { return $this->createNativeDriver(); } /** * Create an instance of the file session driver. * * @return IlluminateSessionStore */ protected function createNativeDriver() { $path = $this->app["config"]["session.files"]; return $this->buildSession(new FileSessionHandler($this->app["files"], $path)); } /** * Build the session instance. * * @param SessionHandlerInterface $handler * @return IlluminateSessionStore */ protected function buildSession($handler) { if ($this->app["config"]["session.encrypt"]) { return new EncryptedStore( $this->app["config"]["session.cookie"], $handler, $this->app["encrypter"] ); } else { return new Store($this->app["config"]["session.cookie"], $handler); } }
這個(gè)Store就是我們Session的實(shí)體了,它的具體讀寫調(diào)用使用抽象的Handler進(jìn)行,也就是說如果是讀文件,就new FileHandler如果是Redis就是new RedisHandler實(shí)現(xiàn)read和write即可。
Session ID回到StartSession 這個(gè)類,我們?cè)倏?b>getSession這個(gè)方法
$session->setId($request->cookies->get($session->getName()));
了解Web的人都應(yīng)該知道,session是根據(jù)cookie中存的key來區(qū)分不同的會(huì)話的,所以sessionId尤為重要,這里我們先不關(guān)心Cookie是如何讀取,我們知道在這里讀取了cookie中存放的SessionId就夠了。
接下去看怎么加載數(shù)據(jù)
Data依然是StartSession這個(gè)類,
我們看startSession這個(gè)方法,下一句調(diào)用的就是$session->start();,這句話是干嘛呢?經(jīng)過前面的分析,我們知道$session已經(jīng)是Store對(duì)象了,那么它的start方法如下:
public function start() { $this->loadSession(); if (! $this->has("_token")) { $this->regenerateToken(); } return $this->started = true; } /** * Load the session data from the handler. * * @return void */ protected function loadSession() { $this->attributes = array_merge($this->attributes, $this->readFromHandler()); foreach (array_merge($this->bags, [$this->metaBag]) as $bag) { $this->initializeLocalBag($bag); $bag->initialize($this->bagData[$bag->getStorageKey()]); } } /** * Read the session data from the handler. * * @return array */ protected function readFromHandler() { $data = $this->handler->read($this->getId()); if ($data) { $data = @unserialize($this->prepareForUnserialize($data)); if ($data !== false && $data !== null && is_array($data)) { return $data; } } return []; }
依次調(diào)用了loadSession和readFromHandler 好,可以看到從handler中調(diào)用了read方法,這個(gè)方法就是從我們之前定義的各種handler中讀取數(shù)據(jù)了,它是個(gè)抽象方法,在子類中具體實(shí)現(xiàn),然后返回給Store(存入到Store中的attributes數(shù)組中去了,到此為止,Session的初始化方法都結(jié)束了,
public function get($name, $default = null) { return Arr::get($this->attributes, $name, $default); }
這個(gè)函數(shù)去讀取Session中的數(shù)據(jù)了。
SummaryOK,Session整個(gè)初始化的過程總結(jié)下:
StartSession#handle -> StartSession#startSession -> StartSession#getSession -> SessionManager#getDefaultDriver -> SessionManager#createXXXHandler -> Store -> Store#setId -> Store#startSession
Laravel巧妙的使用了面向?qū)ο蟮?b>接口方式,為我們提供了各種各樣不同的存儲(chǔ)方式,一旦我們了解了存儲(chǔ)方式和加密規(guī)則,讓不同的web容器進(jìn)行Session共享的目的也可以達(dá)到~
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/21128.html
摘要:在的配置文件中可以設(shè)置,比如這個(gè)項(xiàng)目中設(shè)置名稱為我們可以看到刷新頁面,查看,會(huì)發(fā)現(xiàn)一個(gè)名稱為的,名字就是我們自定義的。而這種加密方式是每次加密的結(jié)果都不同,所以表現(xiàn)為的值每次都發(fā)生了變化,而實(shí)際上并沒有改變。 在 Laravel 的配置文件 config/session.php 中可以設(shè)置 Session Cookie Name,比如這個(gè)項(xiàng)目中設(shè)置名稱為sns_session: /* ...
摘要:服務(wù)器檢查該,以此來辨認(rèn)用戶狀態(tài)。五下的相關(guān)應(yīng)用應(yīng)用在中配置如下配置項(xiàng)用于設(shè)置存儲(chǔ)方式,默認(rèn)是,即存儲(chǔ)在文件中,該文件位于配置項(xiàng)配置的路徑,即。配置項(xiàng)用于設(shè)置有效期,默認(rèn)為分鐘。配置項(xiàng)用于配置數(shù)據(jù)是否加密。 一、cookie的由來 ??當(dāng)用戶訪問某網(wǎng)站時(shí),web服務(wù)器會(huì)將部分信息保存到本地計(jì)算機(jī)上,當(dāng)用戶再次關(guān)顧該網(wǎng)站時(shí),服務(wù)器會(huì)去查看用戶是否登錄過該網(wǎng)站,如果登錄過,就會(huì)將這些記錄在...
摘要:組件擴(kuò)展通常有兩種方法向容器中綁定自己的接口實(shí)現(xiàn)痛過使用工廠模式實(shí)現(xiàn)的類注冊(cè)自己的擴(kuò)展。類庫管理類以工廠模式實(shí)現(xiàn),負(fù)責(zé)諸如緩存等驅(qū)動(dòng)的實(shí)例化。閉包須要傳入繼承自和容器的實(shí)例化對(duì)象。當(dāng)完成擴(kuò)展之后要記住中替換成自己的擴(kuò)展名稱。 聲明:本文并非博主原創(chuàng),而是來自對(duì)《Laravel 4 From Apprentice to Artisan》閱讀的翻譯和理解,當(dāng)然也不是原汁原味的翻譯,能保證9...
摘要:簡介是一套簡介,優(yōu)雅開發(fā)框架,通過簡單,高雅,表達(dá)式語法開發(fā)應(yīng)用。服務(wù)器需要有該目錄及所有子目錄的寫入權(quán)限可用于存儲(chǔ)應(yīng)用程序所需的一些文件該目錄下包括緩存和編譯后的視圖文件日志目錄測(cè)試目錄該目錄下包含源代碼和第三方依賴包環(huán)境配置文件。 簡介 Laravel是一套簡介,優(yōu)雅PHP Web開發(fā)框架(PHP Web Framework), 通過簡單,高雅,表達(dá)式語法開發(fā)Web應(yīng)用。 特點(diǎn): ...
摘要:如何實(shí)現(xiàn)執(zhí)行腳本,會(huì)從中讀取配置項(xiàng),將生成的唯一值保存文件放到配置項(xiàng)中的保存路徑和地點(diǎn)。并通過協(xié)議返回響應(yīng)消息頭名值發(fā)送給客戶端。 1、php如何實(shí)現(xiàn)session 執(zhí)行php腳本,session_start()會(huì)從php.ini中讀取配置項(xiàng),將生成的唯一值sessionID保存文件放到配置項(xiàng)中的保存路徑和地點(diǎn)。并通過HTTP協(xié)議返回響應(yīng)消息頭setCookieCookie名=Cook...
閱讀 991·2021-09-07 09:58
閱讀 1559·2021-09-07 09:58
閱讀 2942·2021-09-04 16:40
閱讀 2552·2019-08-30 15:55
閱讀 2486·2019-08-30 15:54
閱讀 1414·2019-08-30 15:52
閱讀 483·2019-08-30 10:49
閱讀 2651·2019-08-29 13:21