PSR-4オートロードの考え方
PSR-4は、名前空間の階層をそのままディレクトリ構造に対応させるオートロードの規約です。規約に沿えばComposerがrequireなしでクラスを自動的に見つけてくれます。
ネームスペースとディレクトリを対応させる
PSR-4 は「名前空間の階層を、そのままディレクトリ構造に対応させる」という取り決めですね。この規約に沿ってさえいれば、Composer が require なしでクラスを自動的に見つけてくれます。仕組みは単純で、名前空間の接頭辞をあるディレクトリに紐付け、残りの部分をサブディレクトリとファイル名にマッピングするだけです。
// composer.json
{
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
この設定だと、App\Service\UserService というクラスは src/Service/UserService.php を読みに行きます。接頭辞 App\ が src/ に対応し、以降の Service\UserService がそのままパスになるわけですね。クラス名とファイル名は大文字小文字まで一致させる必要があります。
マッピングの読み解き方
ハマりやすいのは、接頭辞に対応するのがディレクトリの「途中」だという点だと思います。App\ が src/ に対応するとき、App の部分はディレクトリ名として現れません。ここを勘違いして src/App/… のように掘ってしまい、クラスが見つからないと悩む、というのはよくある入口の失敗ですね。
// App\Repository\UserRepository の探索先
// 接頭辞 App\ → src/
// 残り Repository\UserRepository → Repository/UserRepository.php
// 結果: src/Repository/UserRepository.php
namespace App\Repository;
final class UserRepository {}
変更したら dump-autoload
composer.json のオートロード設定を書き換えたときや、新しいマッピングを足したときは、composer dump-autoload を忘れると反映されません。生成されたオートロードマップが古いまま、というのが「合っているのに動かない」の典型ですね。開発中は最適化なしのオートローダーで十分ですが、本番では以下のように最適化しておくと解決が速くなります。
// マッピングを変えたら実行
// composer dump-autoload
// 本番向けにクラスマップを事前生成して高速化
// composer dump-autoload --optimize --classmap-authoritative
まとめ
PSR-4 は名前空間とディレクトリを一対一で対応させるだけの素直な規約だと思います。接頭辞がパスの途中に対応する点、大文字小文字を揃える点、設定変更後は dump-autoload する点、この三つを押さえておけば大抵のオートロード問題は自分で切り分けられますね。規約に乗っておくと、require の管理から解放されるのが何よりありがたい気がします。
よくある質問
Q. App\ が src/ に対応するとき src/App/ を作りますか。
A. 作りません。接頭辞のAppはディレクトリ名として現れず、以降の名前空間がそのままパスになります。
Q. クラス名とファイル名の大文字小文字は。
A. 一致させる必要があります。ずれているとクラスが見つかりません。
Q. オートロード設定を変えたのに反映されません。
A. composer dump-autoload を実行してください。生成済みのオートロードマップが古いままだと反映されません。