【PSR-4 Autoload】第一回 autoloadの概要を理解

## この記事でできるようになること :muscle: 
**【第一回】 autoloadの概要を理解**
【第二回】 仕組みを理解したうえでautoloadを実装
【第三回】 composerからautoloadを利用

## そもそも... :thinking: 
### Autoloadとは :mag_right: 
自動的にファイルを読み込んでくれる機能のこと。
必要なファイルを全て`require`するのではなく、autoloadクラスを実装したphpファイルを一回読み込むだけでその都度必要なファイルを読み込んでくれる。

### PSRとは :mag_right: 
PHP Standard Recommendationの略。
PHP-FIGが定めたPHPコーディング規約。

https://www.php-fig.org/

### PSR-4とは :mag_right: 
PSRの中でもAuotloadについての仕様がまとめられている。
命名規則や言葉の意味などについて書かれており、**Autoloadを理解する上で必ず読まなければならない。** が、最初に読んでも驚くほど意味が分からないので、簡単なAutoloadの実装をして（後述）仕組みをざっと理解してから読むのがおすすめ。

https://www.php-fig.org/psr/psr-4/

## 必要となる知識 :books: 
### 最後のチャンス([spl_autoload_register](https://www.php.net/manual/en/function.spl-autoload-register.php "PHP公式ドキュメント")) :warning: 
まずはAutoloadの要となる関数`spl_autoload_register()`について見ていきます。
この関数で何ができるのか、何が有難いのかを理解できると「もしかして私、オートロードいけるかも？」くらい、うふふな気持ちになれます。多分。
逆にこれが理解できないとオートロードとはお友達になれません。
お友達になれる「最後のチャンス」です。
#### 公式Doc :elephant: 
>spl_autoload_register() 関数を使うと、 任意の数のオートローダーを登録でき、クラスやインターフェイスが定義されていなくても自動的に読み込めるようになります。オートローダーを登録すれば、PHPがエラーで止まる前にクラスをロードする最後のチャンスが与えられます。

https://www.php.net/manual/ja/language.oop5.autoload.php

#### 解説 :pencil2: 

通常、未定義のクラスをインスタンス化するとエラーとなる。
```:ディレクトリ構成
./Qiita
    ├ Hello.php (Helloクラスが入っている)
    ├ Autoload.php (後々Autoloadクラスをここに実装する)
    └ index.php (ここからHelloクラスを使いたい)
```
```Hello.php
<?php

class Hello
{
    public function __construct()
    {
        echo "Hello World!";        
    }
}
```
```index.php
<?php
$hello = new Hello();
```
```:Terminal
~\Qiita> php index.php
PHP Fatal error:  Uncaught Error: Class 'Hello' not found in ...
```
そこで事前に`spl_autoload_register()`をコールしておくと、PHPがエラーで止まる前に`spl_autoload_register()`の引数に指定した別の関数を呼び出すことができる。（これがいわゆるコールバック関数）

補足：`spl_autoload_register('callback')`の文法がよくわからない人→[コールバック / Callable](https://www.php.net/manual/ja/language.types.callable.php)

```index.php
<?php

spl_autoload_register('callback');

function callback($className)
{
    var_dump($className); //$classNameに何が入っているのか確認。
    require_once $className . '.php';
}

$hello = new Hello();
```
```:Terminal
\Qiita> php Autoload.php
string(5) "Hello"
Hello World!
```
`callback()`の引数`$className`には呼び出された未定義クラスの**完全修飾クラス名**（後に解説）が入る。今は「クラス名が取得できるんだな」程度の理解でOK。



最後に`$className`と拡張子`.php`を結合し、ファイルを読み込む。

そう、つまり **「クラス名＝ファイル名」** でないとオートロードは動きません。

PSR-4でも "MUST" になっています。
>The terminating class name corresponds to a file name ending in .php. The file name MUST match the case of the terminating class name.
(2.Specification 3.3.より引用)

https://www.php-fig.org/psr/psr-4/#2-specification


次に、`index.php`で行っていたオートロードの処理を`Autoload.php`に`Autoload`クラスとして実装する。
```Autoload.php
<?php

class Autoload{
    public function register(){
        spl_autoload_register(array($this, 'callback'));
    }

    public function callback($className)
    {
        require_once $className . '.php';
    }
}
```
補足：`spl_autoload_register(array($this, 'callback'))`の文法がよくわからない人→[コールバック / Callable](https://www.php.net/manual/ja/language.types.callable.php)（タイプ 3: オブジェクトメソッドのコール参照）
```index.php
<?php
require_once "Autoload.php";
$loader = new Autoload();
$loader->register();

$hello = new Hello();
```
```:Terminal
\Qiita> php index.php
Hello World!
```

うふふな気持ちになれましたか？
今回のAutoloadクラスは、**同じ階層のファイルしか読み込めない**、という重大な欠陥を抱えています。この問題を解決してくれる救世主が「名前空間」です。
詳しくは次回の記事で :wave: 

## その他参考記事・動画 :bookmark: 

https://qiita.com/tadsan/items/942a381e952e12a8fa5a

https://hara-chan.com/it/programming/php-spl_autoload_register/

https://youtu.be/z3pZdmJ64jo

3つ目の動画が個人的にはとてもおすすめです。