国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專(zhuān)欄INFORMATION COLUMN

Laravel學(xué)習(xí)筆記之Session源碼解析(上)

NervosNetwork / 472人閱讀

摘要:然后中間件使用方法來(lái)啟動(dòng)獲取實(shí)例,使用類(lèi)來(lái)管理主要分為兩步獲取實(shí)例,主要步驟是通過(guò)該實(shí)例從存儲(chǔ)介質(zhì)中讀取該次請(qǐng)求所需要的數(shù)據(jù),主要步驟是。

說(shuō)明:本文主要通過(guò)學(xué)習(xí)Laravel的session源碼學(xué)習(xí)Laravel是如何設(shè)計(jì)session的,將自己的學(xué)習(xí)心得分享出來(lái),希望對(duì)別人有所幫助。Laravel在web middleware中定義了session中間件IlluminateSessionMiddlewareStartSession::class,并通過(guò)該中間件來(lái)設(shè)計(jì)session,這個(gè)中間件的主要工作分為三步:(1)啟動(dòng)session,通過(guò)session handler從一些存儲(chǔ)介質(zhì)如redis中讀取session值;(2)操作session,對(duì)session數(shù)據(jù)CRUD增刪改查操作;(3)關(guān)閉session,把session_id寫(xiě)入到response header中,默認(rèn)是laravel_session

開(kāi)發(fā)環(huán)境:Laravel5.3 + PHP7

啟動(dòng)Session

首先看下IlluminateSessionMiddlewareStartSession::class中間件源碼中handle()方法:

    public function handle($request, Closure $next)
    {
        // 前置操作
        $this->sessionHandled = true;

        if ($this->sessionConfigured()) {
            // Start session.
            /**
             * @var IlluminateSessionStore $session
             */
            $session = $this->startSession($request);

            $request->setSession($session);

            $this->collectGarbage($session);
        }

        $response = $next($request);

        // 后置操作
        if ($this->sessionConfigured()) {
            $this->storeCurrentUrl($request, $session);

            $this->addCookieToResponse($response, $session);
        }

        return $response;
    }

從Laravel學(xué)習(xí)筆記之Middleware源碼解析這篇文章中知道,該中間件有前置操作和后置操作。看下sessionConfigured()的源碼:

    /**
     * Determine if a session driver has been configured.
     *
     * @return bool
     */
    protected function sessionConfigured()
    {
        // 檢查session.php中driver選項(xiàng)是否設(shè)置
        return ! is_null(Arr::get($this->manager->getSessionConfig(), "driver"));
    }
    
    // IlluminateSessionSessionManager
    /**
     * Get the session configuration.
     *
     * @return array
     */
    public function getSessionConfig()
    {
        return $this->app["config"]["session"];
    }

首先中間件檢查session.php中driver選項(xiàng)是否設(shè)置,這里假設(shè)設(shè)置為經(jīng)常使用的redis作為session的存儲(chǔ)介質(zhì),并且需要在database.php中設(shè)置下redis的鏈接,本地需要裝好redis,通過(guò)redis-cli命令查看redis是否已經(jīng)安裝好。OK,然后中間件使用startSession()方法來(lái)啟動(dòng)session:

    protected function startSession(Request $request)
    {
        /**
         * @var IlluminateSessionStore $session
         */
        $session = $this->getSession($request); // 獲取session實(shí)例,Laravel使用Store類(lèi)來(lái)管理session

        $session->setRequestOnHandler($request);

        // Load the session data from the store repository by the handler.
        $session->start();

        return $session;
    }
    
    public function getSession(Request $request)
    {
        /**
         * Get the session store instance via the driver.
         *
         * @var IlluminateSessionStore $session
         */
        $session = $this->manager->driver();

        /**
         * $session->getName() === "laravel_session" === config("session.cookie")
         */
        $session->setId($request->cookies->get($session->getName()));

        return $session;
    }

startSession()主要分為兩步:獲取session實(shí)例IlluminateSessionStore,主要步驟是$session = $this->manager->driver();通過(guò)該實(shí)例從存儲(chǔ)介質(zhì)中讀取該次請(qǐng)求所需要的session數(shù)據(jù),主要步驟是$session->start()。首先看下第一步的源碼:

    // IlluminateSupportManager
    public function driver($driver = null)
    {
        // $driver = "redis"
        $driver = $driver ?: $this->getDefaultDriver();
       
        if (! isset($this->drivers[$driver])) {
            $this->drivers[$driver] = $this->createDriver($driver);
        }

        return $this->drivers[$driver];
    }
    
    protected function createDriver($driver)
    {
        $method = "create".Str::studly($driver)."Driver";

        if (isset($this->customCreators[$driver])) {
            return $this->callCustomCreator($driver);
        } elseif (method_exists($this, $method)) { // 判斷IlluminateSessionSessionManager中是否存在createRedisDriver()方法
            // 存在,call這個(gè)createRedisDriver()方法
            return $this->$method();
        }

        throw new InvalidArgumentException("Driver [$driver] not supported.");
    }
    
    // IlluminateSessionSessionManager
    public function getDefaultDriver()
    {
        // 返回 "redis"
        return $this->app["config"]["session.driver"];
    }

從以上源碼中很容易知道,選擇的driver是redis,最后還是要調(diào)用IlluminateSessionSessionManager中的createRedisDriver()方法:

    protected function createRedisDriver()
    {
        /**
         * @var IlluminateSessionCacheBasedSessionHandler $handler
         */
        $handler = $this->createCacheHandler("redis");

        // 設(shè)置redis連接
        $handler->getCache()->getStore()->setConnection($this->app["config"]["session.connection"]);

        return $this->buildSession($handler);
    }
    
    protected function createCacheHandler($driver)
    {
        // $store = "redis"
        $store = $this->app["config"]->get("session.store") ?: $driver;

        $minutes = $this->app["config"]["session.lifetime"];
        
        // $this->app["cache"]->store($store)返回IlluminateCacheRepository實(shí)例
        return new CacheBasedSessionHandler(clone $this->app["cache"]->store($store), $minutes);
    }
    
    // IlluminateSessionCacheBasedSessionHandler
    /**
     * Get the underlying cache repository.
     *
     * @return IlluminateContractsCacheRepository|IlluminateCacheRepository
     */
    public function getCache()
    {
        return $this->cache;
    }
    
    // IlluminateCacheRepository
    /**
     * Get the cache store implementation.
     *
     * @return IlluminateContractsCacheStore|RedisStore
     */
    public function getStore()
    {
        return $this->store;
    }
    
    // IlluminateCacheRedisStore
    /**
     * Set the connection name to be used.
     *
     * @param  string  $connection
     * @return void
     */
    public function setConnection($connection)
    {
        $this->connection = $connection;
    }

從以上源碼知道獲取到IlluminateSessionCacheBasedSessionHandler這個(gè)handler后,就可以buildSession()了:

    protected function buildSession($handler)
    {
        // 設(shè)置加密的則返回EncryptedStore實(shí)例,這里假設(shè)沒(méi)有加密
        if ($this->app["config"]["session.encrypt"]) {
            return new EncryptedStore(
                $this->app["config"]["session.cookie"], $handler, $this->app["encrypter"]
            );
        } else {
            // 默認(rèn)$this->app["config"]["session.cookie"] === "laravel_session"
            return new Store($this->app["config"]["session.cookie"], $handler);
        }
    }

從源碼中可看出session實(shí)例就是IlluminateSessionStore實(shí)例,并且構(gòu)造Store類(lèi)還需要一個(gè)重要的部件handler,構(gòu)造好了session實(shí)例后,就可以通過(guò)這個(gè)handler來(lái)從session存儲(chǔ)的介質(zhì)中如redis獲取session數(shù)據(jù)了,這里設(shè)置的session driver是redis,所以handler就會(huì)是IlluminateSessionCacheBasedSessionHandler。總的來(lái)說(shuō),現(xiàn)在已經(jīng)構(gòu)造好了session實(shí)例即IlluminateSessionStore

然后第二步就是$session->start()從存儲(chǔ)介質(zhì)中加載session數(shù)據(jù):

    public function start()
    {
        // 從存儲(chǔ)介質(zhì)中加載session數(shù)據(jù)
        $this->loadSession();
        
        // session存儲(chǔ)介質(zhì)中沒(méi)有"_token"這個(gè)key就生成一個(gè)
        if (! $this->has("_token")) {
            $this->regenerateToken();
        }

        return $this->started = true;
    }

關(guān)鍵是loadSession()的源碼:

    // Illuminate/Session/Store
    protected function loadSession()
    {
        // 從redis中讀取key為"laravel_session"的數(shù)據(jù)后存入session實(shí)例即Store的$attributes屬性中
        $this->attributes = array_merge($this->attributes, $this->readFromHandler());

        foreach (array_merge($this->bags, [$this->metaBag]) as $bag) {
            /**
             * @var SymfonyComponentHttpFoundationSessionStorageMetadataBag $bag
             */
            $this->initializeLocalBag($bag);

            $bag->initialize($this->bagData[$bag->getStorageKey()]);
        }
    }
    
    protected function readFromHandler()
    {
        // 主要是這句,通過(guò)handler從存儲(chǔ)介質(zhì)redis中讀取session數(shù)據(jù)
        // $this->getId() === "laravel_session"
        $data = $this->handler->read($this->getId());

        if ($data) {
            $data = @unserialize($this->prepareForUnserialize($data));

            if ($data !== false && ! is_null($data) && is_array($data)) {
                return $data;
            }
        }

        return [];
    }

這里的handler是IlluminateSessionCacheBasedSessionHandler,看下該handler的read()源碼:

    // $sessionId === "laravel_session"
    public function read($sessionId)
    {
        // 這里的cache是IlluminateCacheRepository
        return $this->cache->get($sessionId, "");
    }
    
    // IlluminateCacheRepository
    public function get($key, $default = null)
    {
        if (is_array($key)) {
            return $this->many($key);
        }

        // 這里的store是IlluminateCacheRedisStore
        $value = $this->store->get($this->itemKey($key));

        if (is_null($value)) {
            $this->fireCacheEvent("missed", [$key]);

            $value = value($default);
        } else {
            $this->fireCacheEvent("hit", [$key, $value]);
        }

        return $value;
    }
    
    // IlluminateCacheRedisStore
    public function get($key)
    {
        if (! is_null($value = $this->connection()->get($this->prefix.$key))) {
            return $this->unserialize($value);
        }
    }

通過(guò)以上代碼,很容易了解從redis存儲(chǔ)介質(zhì)中加載key為"laravel_session"的數(shù)據(jù),最后還是調(diào)用了RedisStore::get($key, $default)方法。

但不管咋樣,通過(guò)handle()第一步$session = $this->startSession($request);就得到了session實(shí)例即Store,該步驟中主要做了兩步:一是Store實(shí)例化;二是從redis中讀取key為"laravel_session"的數(shù)據(jù)。

然后就是$this->collectGarbage($session)做了垃圾回收。中篇再聊。

總結(jié):本文主要學(xué)習(xí)了session機(jī)制的啟動(dòng)工作中第一步session的實(shí)例化,主要包括兩步驟:Store的實(shí)例化;從redis中讀取key為laravel_session的數(shù)據(jù)。中篇再聊下session垃圾回收,和session的增刪改查操作,到時(shí)見(jiàn)。

歡迎關(guān)注Laravel-China。

RightCapital招聘Laravel DevOps

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/30519.html

相關(guān)文章

  • Laravel學(xué)習(xí)筆記Session源碼解析(中)

    摘要:說(shuō)明在上篇中學(xué)習(xí)了的啟動(dòng)過(guò)程,主要分為兩步,一是的實(shí)例化,即的實(shí)例化二是從存儲(chǔ)介質(zhì)中讀取的數(shù)據(jù)。第二步就是操作,包括對(duì)數(shù)據(jù)的增刪改查操作,本文也主要聊下相關(guān)操作源碼。下篇再學(xué)習(xí)下關(guān)閉,到時(shí)見(jiàn)。 說(shuō)明:在上篇中學(xué)習(xí)了session的啟動(dòng)過(guò)程,主要分為兩步,一是session的實(shí)例化,即IlluminateSessionStore的實(shí)例化;二是從session存儲(chǔ)介質(zhì)redis中讀取id ...

    longshengwang 評(píng)論0 收藏0
  • Laravel學(xué)習(xí)筆記Session源碼解析(下)

    摘要:實(shí)際上,在中關(guān)閉主要包括兩個(gè)過(guò)程保存當(dāng)前到介質(zhì)中在中存入。,學(xué)習(xí)下關(guān)閉的源碼吧先。總之,關(guān)閉的第二件事就是給添加。通過(guò)對(duì)的源碼分析可看出共分為三大步啟動(dòng)操作關(guān)閉。總結(jié)本小系列主要學(xué)習(xí)了的源碼,學(xué)習(xí)了的三大步。 說(shuō)明:在中篇中學(xué)習(xí)了session的CRUD增刪改查操作,本篇主要學(xué)習(xí)關(guān)閉session的相關(guān)源碼。實(shí)際上,在Laravel5.3中關(guān)閉session主要包括兩個(gè)過(guò)程:保存當(dāng)前U...

    Awbeci 評(píng)論0 收藏0
  • Laravel學(xué)習(xí)筆記bootstrap源碼解析

    摘要:總結(jié)本文主要學(xué)習(xí)了啟動(dòng)時(shí)做的七步準(zhǔn)備工作環(huán)境檢測(cè)配置加載日志配置異常處理注冊(cè)注冊(cè)啟動(dòng)。 說(shuō)明:Laravel在把Request通過(guò)管道Pipeline送入中間件Middleware和路由Router之前,還做了程序的啟動(dòng)Bootstrap工作,本文主要學(xué)習(xí)相關(guān)源碼,看看Laravel啟動(dòng)程序做了哪些具體工作,并將個(gè)人的研究心得分享出來(lái),希望對(duì)別人有所幫助。Laravel在入口index...

    xiaoxiaozi 評(píng)論0 收藏0
  • Laravel學(xué)習(xí)筆記IoC Container實(shí)例化源碼解析

    摘要:說(shuō)明本文主要學(xué)習(xí)容器的實(shí)例化過(guò)程,主要包括等四個(gè)過(guò)程。看下的源碼如果是數(shù)組,抽取別名并且注冊(cè)到中,上文已經(jīng)討論實(shí)際上就是的。 說(shuō)明:本文主要學(xué)習(xí)Laravel容器的實(shí)例化過(guò)程,主要包括Register Base Bindings, Register Base Service Providers , Register Core Container Aliases and Set the ...

    ningwang 評(píng)論0 收藏0
  • Laravel學(xué)習(xí)筆記Container源碼解析

    摘要:實(shí)際上的綁定主要有三種方式且只是一種的,這些已經(jīng)在學(xué)習(xí)筆記之實(shí)例化源碼解析聊過(guò),其實(shí)現(xiàn)方法并不復(fù)雜。從以上源碼發(fā)現(xiàn)的反射是個(gè)很好用的技術(shù),這里給出個(gè),看下能干些啥打印結(jié)果太長(zhǎng)了,就不粘貼了。 說(shuō)明:本文主要學(xué)習(xí)Laravel中Container的源碼,主要學(xué)習(xí)Container的綁定和解析過(guò)程,和解析過(guò)程中的依賴(lài)解決。分享自己的研究心得,希望對(duì)別人有所幫助。實(shí)際上Container的綁...

    huayeluoliuhen 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<