猫でもわかるWebプログラミングと副業

本業エンジニアリングマネージャー。副業Webエンジニア。Web開発のヒントや、副業、日常生活のことを書きます。

【PHP】autoload された class が定義されたファイルを確認する

f:id:yoshiki_utakata:20210510220646p:plain

結論

PHP の ReflectionClass を使えば可能です。

<?php 

// 例えば、 CarbonInterface の定義されているファイルが見たい場合
$a = new \ReflectionClass(CarbonInterface::class);
var_dump($a->getFileName());

どういう時に使うの?

PHP には autoload という機能があり、皆さん普通はこの autoload を利用しているかと思います。

しかし、

  • 同じライブラリの複数バージョンがインストールされている
  • 全く同じクラスが複数定義されている

といった場合に、想定と異なるクラスが autoload され、不具合の原因になることがあります。

この時に、「実際にはどのクラスがロードされているのか?」を調べるために、この ReflectionClass::getFileName を利用します。

Carbon と Chronos の例

PHP における DateTime のライブラリとして、 Carbon と Chronos があります。

Chronos は、 CakePHP で開発されたライブラリです。CakePHPはもともと Carbon を採用していましたが、途中から Chronos という独自のライブラリを使うようになりました。

Chronos 1.2.2 以前のバージョンでは、 Carbon との互換性を保つために、以下のコードが入っています。

https://github.com/cakephp/chronos/blob/1.2.2/src/carbon_compat.php

Carbon と Chronos が両方インストールされている環境で、 CarbonInterface を利用しようとすると、上記コードの影響で、 ChronosInterface が読み込まれることになります。

<?php

$a = new \ReflectionClass(CarbonInterface::class);
var_dump($a->getFileName());

結果

..../vendor/cakephp/chronos/src/ChronosInterface.php

Chronos と Laravel

私の場合、Chronos がインストールされた環境に Laravel をインストールしたところ、Laravel が起動せず、 var_dump や ReflectionClass::getFileName を使って地道に調査したところ、 Laravel で使われている Carbon と、すでにインストールされている古いバージョンの Chronos が競合を起こしており、Laravel が起動しないことに気づきました。

PHP では、実際にどのファイルが autoload されているのか、すぐにはわからないため、このテクは有用です。