ホームページ >バックエンド開発 >PHPチュートリアル >Laravelのセッションメカニズムの紹介
数日前、質問に答えるために、Laravel のソースコードを研究し、得られた成果について話しました:
これが問題の原因です:
http://segmentfault.com/q/1010000003776645?_ea =365137
この記事で言及されているすべての Laravel はバージョン 5.1 を使用しています。
まず、Laravel が Session コンポーネントを作成する方法を見てみましょう。
まず、StartSession クラスが Kernerl.php に登録されていることがわかります (Laravel の DI と IoC についてはここでは説明しません)。このクラスがどのように使用されるかを見てみましょう。
このクラスのハンドル メソッドに次のコードがあります
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、典型的なフィルター、この StartSession でセッションを取得するメソッドは getSession です。
Laravel によって挿入された SessionManager を使用します。このクラスの完全修飾名は次のとおりです: IlluminateSessionSessionManager
/** * Start the session for the given request. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Session\SessionInterface */protected function startSession(Request $request){ with($session = $this->getSession($request))->setRequestOnHandler($request); $session->start(); return $session;}/** * Get the session implementation from the manager. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Session\SessionInterface */public function getSession(Request $request){ $session = $this->manager->driver(); $session->setId($request->cookies->get($session->getName())); return $session;}
この関数では、SessionManager のドライブ メソッドを呼び出していることがわかります。ドライブ メソッドは親クラス Manager にあります。 SessionManager の定義が完了しました。その実装は次のようになっています
/** * 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.");}
これは、getDefaultDriver メソッドを呼び出すことです
/** * Get the default session driver name. * * @return string */public function getDefaultDriver(){ return $this->app['config']['session.driver'];}
このフィールドを取得した後、それを取得できます。 createDriver のソースコードより ご覧のとおり、実際には createXXXXDriver を呼び出してドライバーを取得します。
OK、createFileDriver である最も単純なファイルを見てみましょう
このストアは、セッションのエンティティです。つまり、抽象ハンドラーを使用して実行されます。ファイルの場合は、新しい FileHandler を使用します。 Redis の場合は、新しい RedisHandler を使用して読み取りと書き込みを実装します。セッション ID
/** * Create an instance of the file session driver. * * @return \Illuminate\Session\Store */protected function createFileDriver(){ return $this->createNativeDriver();}/** * Create an instance of the file session driver. * * @return \Illuminate\Session\Store */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 \Illuminate\Session\Store */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); }}Web に詳しい人なら誰でも、セッションは Cookie に保存されているキーに基づいて異なるセッション間で区別されることを知っているはずです。そのため、sessionId が特に重要です。ここでは、Cookie を読み取る方法については気にしません。ここでは、Cookie に保存されている SessionId を読み取るだけで十分であることがわかっています。
データをロードする方法を見てみましょう
Data
次の文は $session->start(); を呼び出します。前の分析の後、$session はすでに Store オブジェクトであることがわかっているため、その開始メソッドは次のようになります:
$session->setId($request->cookies->get($session->getName()));loadSession と readFromHandler を順番に呼び出します。これで、read メソッドがハンドラーから呼び出されることがわかります。メソッドは、以前に実行したことです。データは、定義されたさまざまなハンドラーから読み取られ、サブクラスに実装され、ストアに返されます (ストアの属性配列に格納されます)。 、セッションの初期化メソッドが終了しました。
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 [];}この関数は、セッション内のデータを読み取ります。
概要
Laravel はオブジェクト指向のインターフェイス メソッドを巧みに使用しています。さまざまなストレージ方法を提供します。ストレージ方法と暗号化ルールを理解すれば、さまざまな Web コンテナーがセッションを共有できるようにするという目的も達成できます ~