Laravel – $this->guard()

 

ログイン認証の例

たとえばログイン認証のLoginControllerに使われるIllumination\Foundation\Auth\AuthenticatesUsersトレイトlogin()メソッドは次のような内容。

この中で呼ばれているログイン認証処理のattemptLogin()メソッドは、同じトレイトで定義されている。

ここでguard()というメソッドが出てくる。これは同じAuthenticatesUsersトレイトの最後の方で以下のように定義されているが、そもそもどういうものかよくわからなかったので掘り下げてみたら、どんどん深みにはまってしまった。

guard()が見当たらない

AuthenticatesUsersトレイトでAuth::guard()が呼ばれているので、まずAuthクラスについて調べてみる。

AuthクラスはAuthenticatesUsersトレイトの最初で以下のようにuse定義されている。

そこでIlluminate\Foundation\Authクラスを見てみると、コメントにstaticメソッドらしきものが書かれているが、クラス定義の本体にはguard()メソッドが見当たらない。

Authクラスの継承元のIlluminate\Support\Facades\Facadeクラスも見てみたが、useしているトレイトも含めてguard()メソッドは定義されていない。

マジックメソッド__callStatic()を使っている

__callStatic()の内容

いくつかのサイトを参考にしたところ、__callStatic()というマジックメソッドを使っていることがわかってきた。このマジックメソッドは、クラスに定義されていないstaticメソッドが呼ばれた際に実行される。

Facadeクラスを見てみると、以下のように__callStatic()が定義されていた。

最初にあったAuth::guard()スタティックメソッドを呼ぶと、このマジックメソッドが呼ばれ、引数の$method'guard'$argsは空の配列となる。

以下で、この__callStatic()の内容を読んでいく。

getFacadeRoot()

メソッドの最初でgetFacadeRoot()メソッドが呼ばれている。最終的に$instanceにはAuthManagerのインスタンスが返されるが、その道筋を追ってみた。最後の部分だけがまだ理解できておらず、参考サイトの受け売りだが。

このメソッドは同じFacadeクラスで定義されていて、getFacadeAccessor()を引数に与えたresolveFacadeInstance()の戻り値を返している。

getFacadeAccessor()

ここでstaticメソッドgetFacaceAccessor()は、Facadeクラスとこれを継承したAuthクラスの両方で定義されている。

FacadeクラスでのgetFacadeAccessor()の定義は、単に「メソッドが定義されていない」という例外を返す。

一方、Facadeを継承したAuthクラスで定義されたgetFacadeAccessor()は文字列'auth'を返す。

getFacadeRoot()Facadeを継承したAuthクラスから呼ばれると、AuthクラスのstaticメソッドがFacadeクラスのstaticメソッドをオーバーライドして実行される。

この結果、resolveFacadeInstance()の引数には文字列'auth'が与えられる。

resolveFacadeInstance()

引数に'auth'を与えられたresolveFacadeInstance('auth')の挙動を見てみる。

流れは以下の通り。

  • 引数$nameの内容は文字列なので、1つ目のifブロックはスルー。
  • static::$resolvedInstanceFacadeで定義されていて、$nameに対応したインスタンスがあればそのインスタンスが得られる。
  • もしインスタンスが登録されていなければ、最後のifブロックでstatic::$app['auth']の内容が登録されて、そのインスタンスが返される。

この$app['auth']がわからなかった。こちらのサイトの内容をひとまず丸呑みする。

  • static::$appはヘルパーメソッドapp()と同じ動作をする
    • static::$app[‘auth]app()[‘auth’]と同じ意味
    • これはサービスコンテナからauthサービスのインスタンスが起動させる下記のコードと同じことを表す
  • app()->make(‘auth’)で作成されるサービスはIlluminate\Auth\AuthServiceProviderregisterメソッドによって登録されており、Immulminate\Auth\AuthMangaerがインスタンス化されている

__callStatic()の戻り値

$instanceが適正にセットされれば、_callStatic()は以下のように戻り値を返す。

__callStatic()が呼ばれたときの$methodguard()、引数は空だったので、戻り値のメソッドはAuthManager::guard()となる。

guard()はSessionGuard()になる

AuthManager::guard()

結局、attemptLogin()->guard()AuthManager::guard()となり、その内容は以下の通り。

引数なしで呼ばれるので、$nameAuthManager::getDefaultDriver()となる。その内容は以下の通り。

このメソッドは、configディレクトリーにあるauth.phpのdefaultsのキー'guard'に対する値を返す。デフォルトでその内容は'web'となっている。

そして、最後のreturn文にある$this->guards[$name]$this->guards['web']となるが、これが存在しない場合は??演算子の右側が評価されて、AuthManager::resolve('web')が内容としてセットされる。

AuthManager::resolve()

AuthManager::resolve()の内容は以下の通り。

最初の実行文で呼ばれるgetConfig('web')により、config/auth.phpguardsセクションの'web'キーに対応する値が$configとしてセットされる。

auth.phpの該当する部分は以下の通り。

そして、$driverMethodに文字列連結で生成された文字列'createSessionDriver'が格納される。

createSessionDriver()メソッドはAuthManagerに存在するので、ifブロック内の$this->createSessionDriver($name, $config)が実行される。

createSessionDriver()を見ると、$guardとして\Illuminate\Auth\SessionGuardクラスのインスタンスが格納される。

SessionGuardクラスはattempt()メソッドを持つので、最初のattemptLogin()メソッドは以下を実行していることになる。

参考サイト

 

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です