composer の autoload の case-sensitive でハマった
Published: 2021-06-21 23:29:19

mautic を触り始めているが PHP に関しては全然なので初歩的なことにハマった。

## プラグインを作りたかった

簡単なプラグインを作りたくて以下のリポジトリを使ってみようとしてみました。
https://github.com/aviboy2006/mautic-plugin-creator

README に沿って以下を実行。(ddev で実行している）

```bash
> ddev composer require aviboy2006/mautic-plugin-creator
> ddev ssh
$ php vendor/aviboy2006/mautic-plugin-creator/src/test.php
``` 

すると、 `Fatal error: Uncaught Error: Class 'Aviboy2006\MauticPluginCreator\Plugin' not found` のようになってしまう。

## 原因を探す

実行している `test.php` は以下のような簡単なもの。

```php
<?php
use Aviboy2006\MauticPluginCreator\Plugin;
require_once __DIR__ . '/../../../autoload.php';

$greeting = new Plugin();
$greeting->initAction();
$greeting->initialiseBundle();
```

となると、autoload がうまくいっていない可能性が高い。ちなみに PhpStorm 上ではきちんとファイルを認識できていてクラスにジャンプもできている。

### autoload されている一覧を表示する

```php
<?php
$autoloader = require_once __DIR__ . '/../../../autoload.php';
// 一覧を出す
echo json_encode($autoloader->getPrefixesPsr4(), JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);

// ファイルがあるか
$result = $autoloader->findFile('Aviboy2006\MauticPluginCreator\Plugin');
echo json_encode($result);
```

結果としては以下のようになる。

```
// 一覧の中に
    "Aviboy2006\\MauticPluginCreator\\": [
        "/var/www/html/vendor/composer/../aviboy2006/mautic-plugin-creator/src"
    ]

// ファイルがあるか
false
```

つまり、一覧に名前空間は登録されているが、 `Plugin` は取得できていない。

ちなみにプラグインは以下のようになっている。

```php
<?php 

namespace Aviboy2006\MauticPluginCreator;

class Plugin
{
```

ここで気づきましたが、 `Plugin` class のあるファイル名が `plugin.php` になっていました。

PSR-4 のロードは Class 名は Case-Sensitive であるらしく、今回のケースでいえば

```php
$result = $autoloader->findFile('Aviboy2006\MauticPluginCreator\plugin');
// true
```

となる。

- [PSR-4: Autoloader - PHP-FIG](https://www.php-fig.org/psr/psr-4/)
- [PHP の PSR-0 と PSR-4 で autoloader の違いと名前空間の基礎 - Qiita](https://qiita.com/KEINOS/items/2924ecde3e4bab0ead7e)
- [ComposerのクラスオートローダはCase Sensitiveである話](https://genkiroid.github.io/2016/09/10/about-case-mismatch-composer-classmap/)
- [phpのautoloadでclassの読み込みができないとき - Qiita](https://qiita.com/marks_mac_mk2/items/8bac530757738a374d4c)
- [【PHP超入門】名前空間（namespace・use）について - Qiita](https://qiita.com/7968/items/1e5c61128fa495358c1f)
- [「Fatal error: Class ‘…’ not found｣に陥ったときのチェック5項目 - Qiita](https://qiita.com/suin/items/752f3721c4b9084fef4e)
- [初心者がLaravelのindex.phpを読み解いてみた（オートロード編） - Qiita](https://qiita.com/ksrnnb/items/b6f645e70677042755d8)
- [PHPのオートロード(autoload) - Qiita](https://qiita.com/atwata/items/5ba72d3d881a81227c2a)
- [Composer は何者か。あるいは install と update の違い。そしてオートロードの仕組み。](https://gomiba.co/archives/2017/08/883/)
- [public/index.php の最初の三行(vendor/autoload.php の挙動)](https://note.com/gallu/n/ne1bcb25c412a)
- [[PHP]ComposerでAutoload出来ない時の確認方法](https://akamist.com/blog/archives/6)

## optimize することでも動作する

`composer dump-autoload` に `-o` オプションを付けるとマップが作成されるが、そちらは PSR-4 のような名前空間とパスのマップではなく、単純にファイルをリストした上でマップを作成するらしく、上述の名前空間とパス名での case-sensitive の問題は発生しません。

- [composer dumpautoload -o はクラスマップを生成する - Qiita](https://qiita.com/ArimaRyunosuke/items/b47d87b4ab76c35f4c39)
- https://getcomposer.org/doc/03-cli.md
- https://getcomposer.org/doc/articles/autoloader-optimization.md
- [Composer 再入門（その３：オートローダーの最適化） ](https://lazesoftware.com/blog/210320/)
- [[Composer]開発と本番環境を分離する](https://ameblo.jp/itboy/entry-12014177772.html)