2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【PHP】文字列の入った変数をあたかも関数みたいに使ってる記法をたまに見かけるけどあれって何?

Last updated at Posted at 2021-02-26

初めに

タイトルの通りのことをソースコードを眺めているときに思ったのでそれについて調べたことをまとめた備忘録です。

Laravelにより提供されているIlluminate配下のソースコードを眺めているときになんだこれ?って思ったのがきっかけです。

以下、なんだこれ?って思った処理のあるソースコード。

Illuminate/Auth/AuthManager.php
protected function resolve($name)
{
    $config = $this->getConfig($name);

    // ~~中略~~

    $driverMethod = 'create'.ucfirst($config['driver']).'Driver';

    if (method_exists($this, $driverMethod)) {
        return $this->{$driverMethod}($name, $config);  // ★
    }

    // ~~後略~~
}

★のところに注目してください。この部分の$this->{$driverMethod}($name, $config)がなにをしているのかが疑問だったのでその疑問を解決すべく調べてみました。

この表記はどうやら可変関数というらしい

PHP は可変関数(variable functions)の概念をサポートします。 これにより、変数名の後に括弧が付いている場合、その値が何であろうと PHPは、同名の関数を探し実行を試みます。 この機能は、コールバック、関数テーブル等を実装するために使用可能です。
引用:PHP: 可変関数 - Manual

例えば、


function foo()
{
    echo "Foooooo in foo()";
}

$method = "foo";

のようにfoo()と、関数名と同じ名前の文字列を持つ$method変数があったとします。

このとき$method()のように、$methodの後ろに丸括弧を付けてみましょう。

するとPHPが自動で$methodの文字列と同名の関数を探し出して実行してくれます。これが可変関数という概念らしいです。

$method(); // "Foooooo in foo()"が出力される

それを踏まえてさっきのやつを見直してみる

以上で記事の主題は解決しました。ですが、せっかくなので先ほどのIlluminate/Auth/AuthManager.phpがなにをやっているのかを追えるとこまで追っていきましょう。

以下、再掲です。

Illuminate/Auth/AuthManager.php
protected function resolve($name)
{
    $config = $this->getConfig($name);

    // ~~中略~~

    $driverMethod = 'create'.ucfirst($config['driver']).'Driver';  // 1. 

    if (method_exists($this, $driverMethod)) {  // 2.
        return $this->{$driverMethod}($name, $config);  // 3.
    }

    // ~~後略~~
}

このメソッドが呼び出される状況を、

  • $nameには"web"という文字列
  • $configにはgetConfig($name)メソッドによって ['driver' => 'session', 'provider' =>'users']という連想配列

がそれぞれ代入される、というように仮定します。

それを踏まえて番号のついた行を詳しく見てみましょう。

1. の処理

$driverMethod = 'create'.ucfirst($config['driver']).'Driver';  // 1. 

ucfirst()という関数はPHP組み込みの関数で、引数がアルファベットの文字列なら頭文字を大文字に変換して返すという処理をしてくれます。

なので、$config['driver']"session"であることを踏まえると、$driverMethodには'createSessionDriver'という文字列が代入されます。

2.の処理

if (method_exists($this, $driverMethod)) {  // 2.

こちらも1. と同様にmethod_exists()というPHP組み込みの関数が使われています。

これは第1引数に指定したクラスオブジェクトに、第2引数で指定した名前のメソッドが定義されているかを真偽値で返してくれる関数になります。

それを踏まえると2. の処理はAuthManagerクラスにcreateSessionDriverという名前のメソッドが存在するか、という条件分岐を行っている処理だということが分かりました。

3.の処理

return $this->{$driverMethod}($name, $config);  // 3.

3.の処理において先ほど説明した可変関数の概念が使われています。

いままで説明してきたことを踏まえると、この処理は$this->createSessionDriver($name, $config);であるということが明らかとなりました。

以下、本題からそれるので簡単な説明になりますが、このcreateSessionDriver()によってLaravelではセッションによる認証機能の提供が行われることになります。

よく見かける、

Auth::user();

といったAuthファサードによるユーザー情報の取得処理にも、このcreateSessionDriver()から提供されている認証機能が使われています。

終わりに

Laravelのファサードの実体を追っている中で疑問に思ったことをまとめてみました。

次回はファサードの実体がどこにあるかを追ってみて、その調査結果をまとめてみたいと思います。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?