LoginSignup
14
8

More than 5 years have passed since last update.

Laravelが実際に依存オブジェクト注入しているのはどこ??? - Laravelコードリーティング

Last updated at Posted at 2018-05-30

前置き

Laravel5.6のコードを読んでいきます。
DIだとか依存性注入だとかいうけど、実際にはどこで注入してんだよ!ってのが気になったので調べました。

Let's コードリーディング!!!

はじめに、LaravelにはApplicationクラスというのがあります。
bootstrap/app.phpでインスタンスを作ってるやつです。

bootstrap/app.php

$app = new Illuminate\Foundation\Application(
    realpath(__DIR__.'/../')
);

こいつです。こいつをみてみましょう。

vendor/laravel/framework/src/Illuminate/Foundation/Application.php

class Application extends Container implements ApplicationContract, HttpKernelInterface
{
}

Containerクラスを継承してることからわかるように、このApplicationクラスはサービスコンテナ(=DIコンテナ)です。このContainerクラスの中にサービスをインスタンス化するメソッドがあります。

vendor/laravel/framework/src/Illuminate/Container/Container.php

public function make($abstract, array $parameters = [])
{    
    return $this->resolve($abstract, $parameters);
}

こいつです。そのまんまの名前なのでわかりやすいです。
さて、順に追っていきましょう。resolveメソッドをみてみます。
以下、関連する場所だけ抜粋。

vendor/laravel/framework/src/Illuminate/Container/Container.php

protected function resolve($abstract, $parameters = [])
{
    ~~~~

    if ($this->isBuildable($concrete, $abstract)) {
        $object = $this->build($concrete);
    } else {
        $object = $this->make($concrete);
    }

    ~~~~

    return $object;
}

makeを辿ってここまできたのでbuildの方を追ってみます(適当)。
例によって関係ありそうな箇所を抜粋してみます。

vendor/laravel/framework/src/Illuminate/Container/Container.php

public function build($concrete)
{
    if ($concrete instanceof Closure) {
        return $concrete($this, $this->getLastParameterOverride());
    }
    $reflector = new ReflectionClass($concrete);
    $constructor = $reflector->getConstructor();

    $dependencies = $constructor->getParameters();

    $instances = $this->resolveDependencies(
        $dependencies
    );

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

buildメソッドの引数、$concreteにはクラス名かクラスのオブジェクト、もしくはClosureオブジェクトが入ります(たぶん)。
Closureだった場合は実行してreturnしてます。
そうでない場合、ReflectionClassのオブジェクトをつかって依存関係を解決していきます。
ReflectionClassについてはこちらをご参考ください。

あとは順番に読んでいきましょう。

  1. ReflectionClassオブジェクトを利用して、注入先クラス(クライアント)のコンストラクタを取得
  2. コンストラクタのパラメータを取得
  3. resolveDependenciesメソッドで注入する依存オブジェクトのインスタンスを作成(プリミティブなケースは説明を割愛。resolveDependenciesメソッドを読んでみてください。)
  4. ReflectionClassオブジェクトを利用して先ほどインスタンス化した依存オブジェクトを引数に注入先クラス(クライアント)のインスタンスを作成しています。

終わりに

間違いあったら指摘おなしゃーす。

14
8
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
14
8