2017-11-09 9 views
16

Laravelの反射は実際にどのように機能しますか?Laravelの反射はどのように機能しますか?

Laravelがコントローラのコンストラクタでリフレクションを使用して、依存関係や依存関係を解決してから返す方法を見て、デバッグしようとしました。

しかし、私はそれが難しいと感じました。見て、理解し、理解することさえ非常に複雑です。クラスからクラスにジャンプすると、私はそれを実際に見ることができません。私は理解の低い結果でそれをデバッグすることによって数回試しました。

私はこれと反射によって非常に感銘を受けました.Laravelが使用する方法は、私の心が燃え尽きるようにします。それはただ美しいものです。そして私はそれを全面的に理解していきたいと思います。私はそれらがあると思います$x = new TestClass(new TestClass2());

$xは、メソッドの引数からのものであり、通じ構築されるべきTestClass2の別の依存関係を持っているTestClassある

最終的に持つためのルートを打つから始まり、のは言わせ、dd($x)、美しいメカニックスと建築、そしてこれを理解することは、私がとてもひどく欲しいものです。

私の質問は次のとおりです.Laravelのリフレクションは実際にどのように機能していますか?


それはおよそdd男...さんはddせずに言ってみましょうではありません。以前のように - class methodからこのオブジェクトをインスタンス化したときと同じように。ダンプすることではなく、method injectionからreflectionまでです。

ddは一例に過ぎません。 die(var_dump());でも可能です。

+0

ここでは非常に幅広い質問をしていますが、これは*どのようにして*スタイルの質問に最適なフォーラムではありません。 'dd'自体は、オブジェクトに関する個人情報を出力するためにリフレクションを使用します。依存性注入レイヤーは、それを使用してターゲットクラスの依存関係を再帰的に調べます。これは特にLaravel特有のものではありません。変数またはDIをダンプするほとんどのパッケージは、同様のことを行います。 – iainn

+0

@iainn編集された質問 –

+0

Laravelは反射についてのみではありません。ボンネットの下では多くのことが起こっています。 これらの記事を読んで開始: http://alanstorm.com/category/laravel/#container – Hamoud

答えて

27

LaravelはPHPのreflection APIをいくつかのコンポーネントに使用しています。これらのうち、inveron-of-control(IoC)dependency injection containerおよびコントローラmethod injectionは、開発者に最もよく見えます。

function build($className) 
{ 
    $reflector = new ReflectionClass($className); 
    $constructor = $reflector->getConstructor(); 

    foreach ($constructor->getParameters() as $dependency) { 
     $instances[] = build($dependency->getClass()->name); 
    } 

    return $reflector->newInstanceArgs($instances); 
} 

コンセプト、我々が見ることができるように:より明確にここルーチンLaravelのIoC container classは、コンストラクタ・インジェクションによるオブジェクトの依存関係を構築するために使用するの劇的簡易版だ、リフレクションの使用を説明するために

理解することはあまり難しくありません。コンテナはPHPのReflectionClassを使用して、オブジェクトのコンストラクタ内のクラスの名前を見つけ出し、これらの各名前を再帰的にループして、依存関係ツリー内の各オブジェクトのインスタンスを作成します。これらのインスタンスでは、build()は最終的に元のクラスをインスタンス化し、依存関係を引数としてコンストラクタに渡します。

コントローラメソッド注入は、メソッドパラメータとして宣言された依存関係のインスタンスを解決するために、上に示した同一の容器の機能を使用するが、ルートパラメータから別のクラスの依存関係に必要な追加のロジックのビットがあります:再び

function dispatch(Route $route, Controller $controller, $methodName) 
{ 
    $routeParameters = $route->parametersWithoutNulls(); 
    $method = new ReflectionMethod($controller, $methodName); 

    foreach ($method->getParameters() as $index => $parameter) { 
     $class = $parameter->getClass(); 

     if ($class !== null) { 
      $instance = build($class->name); 
      array_splice($routeParameters, $index, 0, [ $instance ]); 
     } 
    } 

    $controller->callAction($methodName, $routeParameters); 
} 

この適応は、リフレクションの役割を強調するためにスリム化され、先に示したbuild()関数に依存しています。ControllerDispatcherクラスはというのメソッドを使用して、コントローラメソッドが予期するパラメータを決定し、これらをループしてコンテナから解決できる依存関係を表すパラメータを検索します。次に、見つかった各依存関係をルートパラメーターの配列にスプライスし、ルートに定義されているコントローラーメソッドに戻します。詳細は、RouteDependencyResolverTraitを参照してください。

アプリケーションのブートストラッププロセスを無視すると、この依存性注入カスケードは通常、Laravelが要求をルートにマップしたときに要求を開始し、次に要求を渡すコントローラを決定します。 Laravelはまずコンテナからコントローラのインスタンスを解決し、コンストラクタがインジェクトした依存関係を構築します。次に、Laravelは適切なコントローラメソッドを見つけ、必要に応じて引数の依存関係を解決します。

ここに示すように、Laravelは、反射を使用してこれらのツールを実装する比較的簡単な手法を使用します。しかし、この答えに示されている例とは異なり、このフレームワークは、今日のように堅牢で柔軟なものにするために、多くの追加コードを追加しています。

関連する問題