Closed1

Laravelのサービスコンテナのmakeを覗いた時のメモ

shira79shira79

make

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

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

第一引数には抽象。

resolve

protected function resolve($abstract, $parameters = [], $raiseEvents = true)
{
~~~
    $concrete = $this->getConcrete($abstract);
~~~
/**
 * Get the concrete type for a given abstract.
 *
 * @param  string  $abstract
 * @return mixed   $concrete
 */
protected function getConcrete($abstract)
{
    if (! is_null($concrete = $this->getContextualConcrete($abstract))) {
        return $concrete;
    }

    // If we don't have a registered resolver or concrete for the type, we'll just
    // assume each type is a concrete name and will attempt to resolve it as is
    // since the container should be able to resolve concretes automatically.
    if (isset($this->bindings[$abstract])) {
        return $this->bindings[$abstract]['concrete'];
    }

    return $abstract;

分岐を通り抜けたら、$abstractを返してる。

resolve関数の中。

// We're ready to instantiate an instance of the concrete type registered for
// the binding. This will instantiate the types, as well as resolve any of
// its "nested" dependencies recursively until all have gotten resolved.
if ($this->isBuildable($concrete, $abstract)) {
    $object = $this->build($concrete);
} else {
    $object = $this->make($concrete);
}

isBuildableだったらbuildする。
もしBuildablじゃなかった場合、具体クラスを引数にまたmakeの処理を通る。

つまり、コンテナに抽象と具体を登録してる場合、2回この関数を通ることになるのかなあ??。一回目は抽象クラスから具体クラスを取得するため。二回目は具体クラスを生成するため。

protected function isBuildable($concrete, $abstract)
{
    return $concrete === $abstract || $concrete instanceof Closure;
}

抽象===具体orクロージャー普通の場合は、buildable。

public function build($concrete)
{
    // If the concrete type is actually a Closure, we will just execute it and
    // hand back the results of the functions, which allows functions to be
    // used as resolvers for more fine-tuned resolution of these objects.
    if ($concrete instanceof Closure) {
        return $concrete($this, $this->getLastParameterOverride());
    }

    $reflector = new ReflectionClass($concrete);

    // If the type is not instantiable, the developer is attempting to resolve
    // an abstract type such as an Interface or Abstract Class and there is
    // no binding registered for the abstractions so we need to bail out.
    if (! $reflector->isInstantiable()) {
        return $this->notInstantiable($concrete);
    }

    $this->buildStack[] = $concrete;

    $constructor = $reflector->getConstructor();

    // If there are no constructors, that means there are no dependencies then
    // we can just resolve the instances of the objects right away, without
    // resolving any other types or dependencies out of these containers.
    if (is_null($constructor)) {
        array_pop($this->buildStack);

        return new $concrete;
    }

    $dependencies = $constructor->getParameters();

    // Once we have all the constructor's parameters we can create each of the
    // dependency instances and then use the reflection instances to make a
    // new instance of this class, injecting the created dependencies in.
    try {
        $instances = $this->resolveDependencies($dependencies);
    } catch (BindingResolutionException $e) {
        array_pop($this->buildStack);

        throw $e;
    }

    array_pop($this->buildStack);

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

上記の抜き出し

$constructor = $reflector->getConstructor();

// If there are no constructors, that means there are no dependencies then
// we can just resolve the instances of the objects right away, without
// resolving any other types or dependencies out of these containers.
if (is_null($constructor)) {
    array_pop($this->buildStack);

    return new $concrete;
}

コンストラクターがnullだったら普通にnewしてる!!!

コンストラクターが存在してたら、以下を通ってるっぽい

またresolveの抜き出し

$dependencies = $constructor->getParameters();

// Once we have all the constructor's parameters we can create each of the
// dependency instances and then use the reflection instances to make a
// new instance of this class, injecting the created dependencies in.
try {
    $instances = $this->resolveDependencies($dependencies);
} catch (BindingResolutionException $e) {
    array_pop($this->buildStack);

    throw $e;
}

array_pop($this->buildStack);

return $reflector->newInstanceArgs($instances);

コンストラクタの引数をとってきて、それをまたコンテナ経由で生成?
生成した$instancesを引数に新たなインスタンスを生成して返す。っていう流れみたい。

このスクラップは2022/02/15にクローズされました