Laravelのオートローダの仕組みが知りたい！

#はじめに
Laravelを勉強していくうちに、Laravelのオートローダの仕組みが知りたくなり、Laravelのオートローダの仕組みについて調べてみました。
調べて分かったことをここにあげるので、興味のある方は是非見てください。
（個人的な都合により、Laravel5.5を対象にオートローダの仕組みを調べました。）
#大雑把な仕組み
**オートローダに関係するファイル**

- publicディレクトリ
    - index.php
- vendorディレクトリ
    - autoload.php
    - composerディレクトリ
        - autoload_classmap.php
        - autoload_namespaces.php
        - autoload_psr4.php
        - autoload_real.php
        - autoload_static.php
        - ClassLoader.php

**それぞれの役割**
1. オートローダの読み込み（index.php）
2. オートローダの実行（autoload.php）
3. オートローダの実装（autoload_real.php）
4. オートローダの対象のファイルデータの格納（autoload_classmap.php, autoload_namespace.php, autoload_psr4.php, autoload_static.php）
5. ファイルデータの読み込み（ClassLoader.php）

           


#実際に作ってみた
オートローダーの仕組みを使い、こんなことをやってみました。

**やってみたこと**
使用したい機能が実装されているファイルを直接requireしなくても、その機能が実行したいファイル上で実行できるようにすること。

**使用したファイル**

- 親ディレクトリ
    - appディレクトリ
        - Application.php
    - app.php
    - autoloader_real.php
    - autoloader_static.php
    - autoload.php
    - ClassLoader.php

**それぞれの役割**
1. オートローダの読み込み（index.php）
2. オートローダの実行（autoload.php）
3. オートローダの実装（autoload_real.php）
4. オートローダの対象のファイルデータの格納（ autoload_static.php）
5. ファイルデータの読み込み（ClassLoader.php）
6. 使いたい機能（Application.php）

**実際のコード**
Application.phpの機能は、App\Applicationクラスのインスタンスから、successメソッドを実行すると、「Success!」の文字が表示される。

``` .../app/Application.php
<?php
namespace App;
/**
 *
 */
class Application
{

  public function success()
  {
    echo 'Success!';
  }
}
?>
```
このファイルのデータを格納しているautoload_static.phpのコードは

```.../autoload_static.php
<?php
namespace Vendor;
/**
 *
 */
class Autoload_real
{
  public static $classMap = array('App\\Application' => __DIR__.'\app\Application.php');
  public static function getInitializer(ClassLoader $loader)
  {
    return \Closure::bind(function () use ($loader)
    {
      $loader->classMap = Autoload_real::$classMap;
    }, null, ClassLoader::class);
  }
}

?>
```
その格納しているファイルデータを読み込んでいるClassLoader.phpのコードは

```.../ClassLoader.php
<?php
namespace Vendor;
/**
 *
 */
class ClassLoader
{
  private $classMap = array();

  function register($prepend = false)
  {
    spl_autoload_register(array($this, 'loadClass'), true, $prepend);
  }

  public function loadClass($class)
  {
    if ($file = $this->findfile($class)) {
      include $file;
    }
  }

  public function findfile($class)
  {
    if (isset($this->classMap[$class])) {
      return $this->classMap[$class];
    } else {
      return false;
    }
  }
}

?>
```
読み込んだファイルデータを基にオートローダの実装を行っているautoload_real.phpのコードは

```.../autoload_real.php
<?php
require __DIR__.'/ClassLoader.php';
/**
 *
 */
class Autoload_real
{
  private static $loader;

  function getLoader()
  {
    $loader = new Vendor\ClassLoader();

    require 'autoload_static.php';
    call_user_func(Vendor\Autoload_real::getInitializer($loader));

    $loader->register(true);

    return $loader;
  }
}

?>
```
実装したオートローダを実行するautoload.phpのコードは

``` .../autoload.php
<?php
require_once 'autoload_real.php';

return Autoload_real::getLoader();
?>
```
最後にオートローダを読み込むindex.phpのコードは

```.../index.php
<?php
require 'autoload.php';

$app = new App\Application.php();

$app->success(); //「Success!」と表示される。
?>
```
    
#終わりに
今回はLaravelのオートローダについてざっくり見てみました。
オートローダの仕組みを調べるのは大変でしたが楽しかったので、今後もLaravelの他の機能についても調べてみたいと思います。