routes/web.php が読み込まれて実行されるまでを理解する

# まえがき

## 背景

エンジニア仲間でLaravelのソースコードを輪読することにしました。Laravelのソースコードとは言っても膨大な量があるので、まずはルーティング処理から読んでいきます。

1回目の先週はKernelやFacadeなどの概念をさらいながら `App\Providers\RouteServiceProvider` クラスの `mapWebRoutes()` メソッドを読むという発表がありました。2回目の今日はルーティング情報の設定がどのように行われるのかを厳密に読んでいきたいと思います。

## ローカル開発環境

macOSです。

```
> sw_vers -productVersion 
10.15.4
> php --version
PHP 7.2.30 (cli) (built: Apr 23 2020 02:40:39) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.2.30, Copyright (c) 1999-2018, by Zend Technologies
> composer --version
Composer version 1.10.5 2020-04-10 11:44:22
```

## ソースコードを読むアプリケーションの作成方法

今回読むソースコードは [Installation - Laravel - The PHP Framework For Web Artisans > Installing Laravel](https://laravel.com/docs/7.x/installation#installing-laravel) の **Via Laravel Installer** に書いてある手順に従ってローカルで作成したものです。

# `routes/web.php` を見てみよう

```php:routes/web.php
<?php

use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
    return view('welcome');
});

```

## `routes/web.php` は何ですか？

長部はこのように理解しています ↓

- 私たち **アプリケーションの開発者が編集するファイル** である。すなわち、フレームワークのファイルではなく、アプリケーションによって異なるファイルである。
- ブラウザからアプリケーションにアクセスされた時の **ルーティング情報を記述するファイル** である。ここで、 **ルーティング情報** という用語を「これこれのHTTPメソッドでこれこれのURIをリクエストされたとき、これこれのControllerのこれこれのActionを実行する」もしくは「これこれのHTTPメソッドでこれこれのURIをリクエストされたとき、これこれのViewをレンダリングしてレスポンスを返す」といった情報の意味で使っている。また、 **ブラウザ** と言ったが、これは **Webクライアント** の方が正確である。
- HTTPリクエストのうち、 **ユーザーが見るページのルーティング情報を記述するファイル** であって、APIなどユーザーがレスポンスを直接は見ないリクエストを記述するファイルではない。

参考文献 ↓

- [Routing - Laravel - The PHP Framework For Web Artisans > Basic Routing](https://laravel.com/docs/7.x/routing#basic-routing) > The Default Route Files

## 次は何をしますか？

- `Route::get('/', function () { ... });` を実行した時に起きることを1段階深掘りします。
- 深掘りする過程で、必要なら `routes/web.php` が読み込まれるまでに起きることを理解します。

# `Illuminate\Support\Facades\Route` の定義を見てみよう

```php:vendor/laravel/framework/src/Illuminate/Support/Facades/Route.phpから抜粋
<?php

namespace Illuminate\Support\Facades;

/**
 * @method static \Illuminate\Routing\Route fallback(array|string|callable|null $action = null)
 * (中略)
 * @method static \Illuminate\Routing\Route getCurrentRoute()
 *
 * @see \Illuminate\Routing\Router
 */
class Route extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'router';
    }
}
```

`Illuminate\Support\Facades\Route` [クラス](https://www.php.net/manual/ja/language.oop5.basic.php)は `Illuminate\Support\Facades\Facade` [クラス](https://www.php.net/manual/ja/language.oop5.abstract.php)を継承していることがわかったので、 `Illuminate\Support\Facades\Facade` の定義も見てみましょう。

```php:vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.phpから抜粋
<?php

namespace Illuminate\Support\Facades;

use Closure;
use Mockery;
use Mockery\MockInterface;
use RuntimeException;

abstract class Facade
{
    /**
     * The application instance being facaded.
     *
     * @var \Illuminate\Contracts\Foundation\Application
     */
    protected static $app;

    // 中略

    /**
     * Handle dynamic, static calls to the object.
     *
     * @param  string  $method
     * @param  array  $args
     * @return mixed
     *
     * @throws \RuntimeException
     */
    public static function __callStatic($method, $args)
    {
        $instance = static::getFacadeRoot();

        if (! $instance) {
            throw new RuntimeException('A facade root has not been set.');
        }

        return $instance->$method(...$args);
    }
}

```

この2つのファイルを見ると、 `Route::get('/', function () { ... });` を1段階深掘りするためには **`Illuminate\Support\Facades\Route` クラスか `Illuminate\Support\Facades\Facade` クラスの定義を読めばいい** ことがわかります。その理由は以下のようなものです ↓

- `Illuminate\Support\Facades\Route` クラスは `Illuminate\Support\Facades\Facade` クラスを継承している。
- `Illuminate\Support\Facades\Facade` クラスはどっかの[クラスを継承](https://www.php.net/manual/ja/language.oop5.inheritance.php)していない。
- ~~2つのクラスともどっかの[インターフェース](https://www.php.net/manual/ja/language.oop5.interfaces.php)を実装していない。~~ => メソッドの実装を探すときにはインターフェースを見る必要がないことに気づいたのですが、PHPマニュアルへのリンクを残したいので打ち消し線を引いておきました。
- 2つのクラスともどっかの[トレイト](https://www.php.net/manual/ja/language.oop5.traits.php)を追加していない。

## `Route::get()` メソッドの実装はどこにありますか？

結論はこうです ↓

- 1段階深掘りするなら `Route::get()` の実装は **`Illuminate\Support\Facades\Facade` クラスの `__callStatic()` メソッド** である。
- それ以上深掘りするとなんだかよくわからなくなる。

`Illuminate\Support\Facades\Facade::__callStatic()` メソッドを読めばいいという結論に至る過程は以下のようなものです ↓

1. `Illuminate\Support\Facades\Route` クラスには `get()` メソッドが定義されていない。
2. `Illuminate\Support\Facades\Route` クラスの親クラスである `Illuminate\Support\Facades\Facade` クラスにも `get()` メソッドが定義されていない。
3. 2つのクラスともどっかのトレイトを追加しているわけではないため、 `get()` メソッドの実装がどっか別のトレイトで定義されているわけでもない。
4. 明示的な実装が定義されていないなら[マジックメソッド](https://www.php.net/manual/ja/language.oop5.magic.php) `__callStatic()` が定義されていないとおかしい。

## `Route::get()` を実行した時に何が起きますか？

↓ これを実行することは、

```php
Route::get('/', function () {
    return view('welcome');
});
```

↓ これを実行することと同じと考えてよいです。

```php
Illuminate\Support\Facades\Route::__callStatic('get', [
    '/',
    function () {
        return view('welcome');
    },
]);
```

[PHP: オーバーロード - Manual > メソッドのオーバーロード](https://www.php.net/manual/ja/language.oop5.overloading.php#language.oop5.overloading.methods) によれば、 `__callStatic()` メソッドの第一引数には「コールしようとしたメソッドの名前」すなわち `'get'` が入り、第二引数には「メソッドに渡そうとしたパラメータが配列で」すなわち要素が `function () { ... }` だけからなる配列 `[function () { ... }]` が入ります。

`__callStatic()` メソッドが定義されているクラスは `Illuminate\Support\Facades\Facade` ですが、メソッドを呼び出し元のクラスは `Illuminate\Support\Facades\Route` です。

`__callStatic()` メソッドの中の `static::` は今回の場合は `Illuminate\Support\Facades\Route` [クラスに解決される](https://www.php.net/manual/ja/language.oop5.static.php)ので、まずは `Illuminate\Support\Facades\Route::getFacadeRoot()` メソッドが実行されて返り値が `$instance` に代入され、例外処理をした後に `$instance` オブジェクトの `get()` メソッドが `function () { ... }` を引数として呼び出されます。

## 次は何をしますか？

- `$instance = static::getFacadeRoot()` を実行した時に起きることを1段階深掘りします。
- 深掘りする過程で、必要なら `routes/web.php` が読み込まれるまでに起きることを理解します。

# `Illuminate\Support\Facades\Facade::getFacadeRoot()` の定義を見てみよう

```php:vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.phpから抜粋
/**
 * Get the root object behind the facade.
 *
 * @return mixed
 */
public static function getFacadeRoot()
{
    return static::resolveFacadeInstance(static::getFacadeAccessor());
}
```

`getFacadeRoot()` メソッドの中の `static::` は今回も `Illuminate\Support\Facades\Route` クラスに解決されます。 `resolveFacadeInstance()` メソッドは `Illuminate\Support\Facades\Route` クラスには定義されておらず、 `Illuminate\Support\Facades\Facade` クラスに定義されているのでそれを見てみましょう。

```php:vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.phpから抜粋
/**
 * Resolve the facade root instance from the container.
 *
 * @param  object|string  $name
 * @return mixed
 */
protected static function resolveFacadeInstance($name)
{
    if (is_object($name)) {
        return $name;
    }

    if (isset(static::$resolvedInstance[$name])) {
        return static::$resolvedInstance[$name];
    }

    if (static::$app) {
        return static::$resolvedInstance[$name] = static::$app[$name];
    }
}
```

`getFacadeAccessor()` メソッドは `Illuminate\Support\Facades\Route` クラスに定義されているのでそれも見てみましょう。

```php:vendor/laravel/framework/src/Illuminate/Support/Facades/Route.phpから抜粋
/**
 * Get the registered name of the component.
 *
 * @return string
 */
protected static function getFacadeAccessor()
{
    return 'router';
}
```

## `$instance = static::getFacadeRoot()` を実行した時に何が起きますか？

↓ これを実行することは、

```php
$instance = static::getFacadeRoot();
```

↓ これを実行することと同じと考えてよいです。

```php
$instance = Illuminate\Support\Facades\Facade::resolveFacadeInstance('router');
```

`$name = 'router'` は文字列なので以下はスキップされます ↓

```php
if (is_object($name)) {
    return $name;
}
```

`static::$resolvedInstance[$name]` が存在して `NULL` でない時には `static::$resolvedInstance[$name]` をそのまま返しているので、今回は `static::$resolvedInstance[$name]` が存在しないか `NULL` でない時のことを考えます。この場合は以下の処理が行われます ↓

1. `static::$app[$name]` を取得して `static::$resolvedInstance[$name]` に代入します。
2. `static::resolveFacadeInstance()` は `static::$resolvedInstance[$name]` を返します。
3. `static::getFacadeRoot()` はそのままそれを返します。
4. `Illuminate\Support\Facades\Facade::__callStatic()` の中の `$instance` にはそれがそのまま代入されます。

以上のステップの `static::` は全て `Illuminate\Support\Facades\Route` クラスに解決されます。したがって `Illuminate\Support\Facades\Route::$app['router']` の中身がわかれば `return $instance->$method(...$args)` を実行した時に何が起きるかを1段階深掘りすることができます。

## 次は何をしますか？

- `Illuminate\Support\Facades\Route::$app['router']` の中身を1段階深掘りします。
- 深掘りする過程で、必要なら `routes/web.php` が読み込まれるまでに起きることを理解します。

# Illuminate\Support\Facades\Route::$app には何が入っているのか調べよう

`Illuminate\Support\Facades\Route` クラスには `$app` というクラスプロパティは定義されていません。 `Illuminate\Support\Facades\Route` クラスの親クラスである `Illuminate\Support\Facades\Facade` クラスには `$app` というクラスプロパティが定義されているため、 `Illuminate\Support\Facades\Route::$app` はこちらを指しています。

```php:vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.phpから抜粋
/**
 * The application instance being facaded.
 *
 * @var \Illuminate\Contracts\Foundation\Application
 */
protected static $app;
```

結論から言ってしまうと `Illuminate\Support\Facades\Facade::$app` には `Illuminate\Foundation\Application` クラスのシングルトンが入っています。 `Illuminate\Support\Facades\Facade::$app` に `Illuminate\Foundation\Application` クラスのシングルトンが入るまでを厳密に追うのには時間がかかるので、気になった方が追いやすくなるように細部を省いてプロットしておきます。

## public/index.php

`bootstrap/app.php` を読み込んで実行し、返り値を `$app` に代入しています。

```php:public/index.phpから抜粋
/*
|--------------------------------------------------------------------------
| Turn On The Lights
|--------------------------------------------------------------------------
|
| We need to illuminate PHP development, so let us turn on the lights.
| This bootstraps the framework and gets it ready for use, then it
| will load up this application so that we can run it and send
| the responses back to the browser and delight our users.
|
*/

$app = require_once __DIR__.'/../bootstrap/app.php';
```

## bootstrap/app.php

`$app` には `Illuminate\Foundation\Application` クラスのインスタンスが入ります。

```php:bootstrap/app.phpから抜粋
/*
|--------------------------------------------------------------------------
| Create The Application
|--------------------------------------------------------------------------
|
| The first thing we will do is create a new Laravel application instance
| which serves as the "glue" for all the components of Laravel, and is
| the IoC container for the system binding all of the various parts.
|
*/

$app = new Illuminate\Foundation\Application(
    $_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
);
```

↓ こんな設定をしています。

- `$app` が「 `Illuminate\Contract\Http\Kernel` インターフェースを実装したクラスのインスタンスを作れ」と言われたら、 `$app` は `App\Http\Kernel` クラスのインスタンスを作る。
- `App\Http\Kernel` クラスのインスタンスは1つしか作られない。すなわちシングルトンである。

```php:bootstrap/app.phpから抜粋
/*
|--------------------------------------------------------------------------
| Bind Important Interfaces
|--------------------------------------------------------------------------
|
| Next, we need to bind some important interfaces into the container so
| we will be able to resolve them when needed. The kernels serve the
| incoming requests to this application from both the web and CLI.
|
*/

$app->singleton(
    Illuminate\Contracts\Http\Kernel::class,
    App\Http\Kernel::class
);
```

## public/index.php 再び

`$kernel` には `App\Http\Kernel` クラスのインスタンスが入ります。

```php:public/index.phpから抜粋
/*
|--------------------------------------------------------------------------
| Run The Application
|--------------------------------------------------------------------------
|
| Once we have the application, we can handle the incoming request
| through the kernel, and send the associated response back to
| the client's browser allowing them to enjoy the creative
| and wonderful application we have prepared for them.
|
*/

$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
```

`App\Http\Kernel` クラスの `handle()` メソッドを呼び出します。

```php:public/index.phpから抜粋
$response = $kernel->handle(
    $request = Illuminate\Http\Request::capture()
);
```

## Illuminate\Foundation\Http\Kernel

`App\Http\Kernel` クラスは `Illuminate\Foundation\Http\Kernel` クラスを継承しており、 `handle()` メソッドはこちらのクラスに定義されています。

```php:vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.phpから抜粋
/**
 * Handle an incoming HTTP request.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return \Illuminate\Http\Response
 */
public function handle($request)
{
    try {
        $request->enableHttpMethodParameterOverride();

        $response = $this->sendRequestThroughRouter($request);
    } catch (Throwable $e) {
        $this->reportException($e);

        $response = $this->renderException($request, $e);
    }

    $this->app['events']->dispatch(
        new RequestHandled($request, $response)
    );

    return $response;
}
```

`$request->enableHttpMethodParameterOverride();` はすっ飛ばして `$response = $this->sendRequestThroughRouter($request)` を深掘りします。

```php:vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.phpから抜粋
/**
 * Send the given request through the middleware / router.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return \Illuminate\Http\Response
 */
protected function sendRequestThroughRouter($request)
{
    $this->app->instance('request', $request);

    Facade::clearResolvedInstance('request');

    $this->bootstrap();

    return (new Pipeline($this->app))
                ->send($request)
                ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
                ->then($this->dispatchToRouter());
}
```

いろいろすっ飛ばして `$this->bootstrap();` を深掘りします。

```php:vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.phpから抜粋
/**
 * Bootstrap the application for HTTP requests.
 *
 * @return void
 */
public function bootstrap()
{
    if (! $this->app->hasBeenBootstrapped()) {
        $this->app->bootstrapWith($this->bootstrappers());
    }
}
```

条件分岐はすっ飛ばして `$this->app->bootstrapWith($this->bootstrappers());` を深掘りします。まずは `Illuminate\Foundation\Http\Kernel` クラスの `bootstrappers()` メソッドから読みます。

```php:vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.phpから抜粋
/**
 * Get the bootstrap classes for the application.
 *
 * @return array
 */
protected function bootstrappers()
{
    return $this->bootstrappers;
}
```

`$this->bootstrappers` も `Illuminate\Foundation\Http\Kernel` クラスに定義されています。

```php:vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.phpから抜粋
/**
 * The bootstrap classes for the application.
 *
 * @var array
 */
protected $bootstrappers = [
    \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class,
    \Illuminate\Foundation\Bootstrap\LoadConfiguration::class,
    \Illuminate\Foundation\Bootstrap\HandleExceptions::class,
    \Illuminate\Foundation\Bootstrap\RegisterFacades::class,
    \Illuminate\Foundation\Bootstrap\RegisterProviders::class,
    \Illuminate\Foundation\Bootstrap\BootProviders::class,
];
```

## Illuminate\Foundation\Bootstrap\RegisterFacades

`Illuminate\Foundation\Bootstrap\RegisterFacades` クラスは小さいので貼ってしまします。

```php:vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/RegisterFacades.php
<?php

namespace Illuminate\Foundation\Bootstrap;

use Illuminate\Contracts\Foundation\Application;
use Illuminate\Foundation\AliasLoader;
use Illuminate\Foundation\PackageManifest;
use Illuminate\Support\Facades\Facade;

class RegisterFacades
{
    /**
     * Bootstrap the given application.
     *
     * @param  \Illuminate\Contracts\Foundation\Application  $app
     * @return void
     */
    public function bootstrap(Application $app)
    {
        Facade::clearResolvedInstances();

        Facade::setFacadeApplication($app);

        AliasLoader::getInstance(array_merge(
            $app->make('config')->get('app.aliases', []),
            $app->make(PackageManifest::class)->aliases()
        ))->register();
    }
}
```

## Illuminate\Support\Facades\Facade

`Illuminate\Support\Facades\Facade` クラスの `setFacadeApplication()` メソッドの定義も貼っておきます。

```php:vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.phpから抜粋
/**
 * Set the application instance.
 *
 * @param  \Illuminate\Contracts\Foundation\Application  $app
 * @return void
 */
public static function setFacadeApplication($app)
{
    static::$app = $app;
}
```

最後に `Illuminate\Foundation\Application` クラスの `bootstrapWith()` メソッドを読めば全部繋がります。

## Illuminate\Foundation\Application

```php:vendor/laravel/framework/src/Illuminate/Foundation/Application.phpから抜粋
/**
 * Run the given array of bootstrap classes.
 *
 * @param  string[]  $bootstrappers
 * @return void
 */
public function bootstrapWith(array $bootstrappers)
{
    $this->hasBeenBootstrapped = true;

    foreach ($bootstrappers as $bootstrapper) {
        $this['events']->dispatch('bootstrapping: '.$bootstrapper, [$this]);

        $this->make($bootstrapper)->bootstrap($this);

        $this['events']->dispatch('bootstrapped: '.$bootstrapper, [$this]);
    }
}
```

## 次は何をしますか？

- `Illuminate\Support\Facades\Route::$app['router']` の中身をもう1段階深掘りします。
- 深掘りする過程で、必要なら `routes/web.php` が読み込まれるまでに起きることを理解します。

# Illuminate\Support\Facades\Route::$app['router'] には何が入っているのか調べよう

`$app` はオブジェクトなのに、配列のように `$app['router']` という記述がされています。まずはこれがどうやって動くのかを調べます。

`Illuminate\Foundation\Application` クラスは `Illuminate\Container\Container` クラスを継承しており、 `Illuminate\Container\Container` クラスは `ArrayAccess` というインターフェースを実装しています。 `ArrayAccess` は [SPL(Standard PHP Library)で定義されているインターフェースの1つ](https://www.php.net/manual/ja/class.arrayaccess.php) で、次の4つのメソッドを定義してやることでオブジェクトに対して配列のようなアクセスをすることが可能になります。

- offsetExists()
- offsetGet()
- offsetSet()
- offsetUnset()

## Illuminate\Container\Container クラスの offsetGet() メソッド

`$app['router']` を取得しようとしたときは `$app` に入っているオブジェクトの `offsetGet()` メソッドが呼び出されます。これは `Illuminate\Container\Container` クラスに定義されています。

```php:vendor/laravel/framework/src/Illuminate/Container/Container.phpから抜粋
/**
 * Get the value at a given offset.
 *
 * @param  string  $key
 * @return mixed
 */
public function offsetGet($key)
{
    return $this->make($key);
}
```

## Illuminate\Foundation\Application クラスの make() メソッド

`offsetGet()` メソッドを呼び出したオブジェクト `$app` は `Illuminate\Foundation\Application` クラスのインスタンスなので、まずは `Illuminate\Foundation\Application` クラスに定義されている `make()` メソッドが呼ばれます。

```php:vendor/laravel/framework/src/Illuminate/Foundation/Application.phpから抜粋
/**
 * Resolve the given type from the container.
 *
 * @param  string  $abstract
 * @param  array  $parameters
 * @return mixed
 */
public function make($abstract, array $parameters = [])
{
    $this->loadDeferredProviderIfNeeded($abstract = $this->getAlias($abstract));

    return parent::make($abstract, $parameters);
}
```

## Illuminate\Container\Container クラスの make() メソッド

返される値は `parent::make($abstract, $parameters)` なので、 `$this->loadDeferredProviderIfNeeded($abstract = $this->getAlias($abstract));` は飛ばして `Illuminate\Container\Container` クラスの `make()` メソッドを貼ります。

```php:vendor/laravel/framework/src/Illuminate/Container/Container.phpから抜粋
/**
 * Resolve the given type from the container.
 *
 * @param  string  $abstract
 * @param  array  $parameters
 * @return mixed
 *
 * @throws \Illuminate\Contracts\Container\BindingResolutionException
 */
public function make($abstract, array $parameters = [])
{
    return $this->resolve($abstract, $parameters);
}
```

## Illuminate\Foundation\Application クラスの resolve() メソッド

`offsetGet()` メソッドを呼び出したオブジェクト `$app` は `Illuminate\Foundation\Application` クラスのインスタンスなので、戻って `Illuminate\Foundation\Application` クラスに定義されている `resolve()` メソッドが呼ばれます。

```php:vendor/laravel/framework/src/Illuminate/Foundation/Application.phpから抜粋
/**
 * Resolve the given type from the container.
 *
 * @param  string  $abstract
 * @param  array  $parameters
 * @param  bool  $raiseEvents
 * @return mixed
 */
protected function resolve($abstract, $parameters = [], $raiseEvents = true)
{
    $this->loadDeferredProviderIfNeeded($abstract = $this->getAlias($abstract));

    return parent::resolve($abstract, $parameters, $raiseEvents);
}
```

## Illuminate\Container\Container クラスの resolve() メソッド

返される値は `parent::resolve($abstract, $parameters, $raiseEvents)` なので、 `$this->loadDeferredProviderIfNeeded($abstract = $this->getAlias($abstract));` は飛ばして `Illuminate\Container\Container` クラスの `resolve()` メソッドを貼ります。

```php:vendor/laravel/framework/src/Illuminate/Container/Container.phpから抜粋
/**
 * Resolve the given type from the container.
 *
 * @param  string  $abstract
 * @param  array  $parameters
 * @param  bool  $raiseEvents
 * @return mixed
 *
 * @throws \Illuminate\Contracts\Container\BindingResolutionException
 */
protected function resolve($abstract, $parameters = [], $raiseEvents = true)
{
    $abstract = $this->getAlias($abstract);

    $concrete = $this->getContextualConcrete($abstract);

    $needsContextualBuild = ! empty($parameters) || ! is_null($concrete);

    // If an instance of the type is currently being managed as a singleton we'll
    // just return an existing instance instead of instantiating new instances
    // so the developer can keep using the same objects instance every time.
    if (isset($this->instances[$abstract]) && ! $needsContextualBuild) {
        return $this->instances[$abstract];
    }

    $this->with[] = $parameters;

    if (is_null($concrete)) {
        $concrete = $this->getConcrete($abstract);
    }

    // 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);
    }

    // If we defined any extenders for this type, we'll need to spin through them
    // and apply them to the object being built. This allows for the extension
    // of services, such as changing configuration or decorating the object.
    foreach ($this->getExtenders($abstract) as $extender) {
        $object = $extender($object, $this);
    }

    // If the requested type is registered as a singleton we'll want to cache off
    // the instances in "memory" so we can return it later without creating an
    // entirely new instance of an object on each subsequent request for it.
    if ($this->isShared($abstract) && ! $needsContextualBuild) {
        $this->instances[$abstract] = $object;
    }

    if ($raiseEvents) {
        $this->fireResolvingCallbacks($abstract, $object);
    }

    // Before returning, we will also set the resolved flag to "true" and pop off
    // the parameter overrides for this build. After those two things are done
    // we will be ready to return back the fully constructed class instance.
    $this->resolved[$abstract] = true;

    array_pop($this->with);

    return $object;
}
```

ここで頭が爆発したのでレジュメはここまでです。輪講までに理解できたらその場で話すかもです。