クラスが見つからないエラー「Fatal error: Class ‘○○○’ not found」が発生したとき、その典型的な原因とその対処方法をチェックリスト形式で紹介します。
vendor/autoload.phpをrequireしているか?
composer install
で必要なライブラリをインストールして、いざ使おうとしたらFatalになるパターンです。たとえば、guzzlehttp/guzzle
をインストールして、
composer require guzzlehttp/guzzle
main.phpでGuzzleHttp\Client
をnew
するコードを書いて、
<?php
$client = new GuzzleHttp\Client();
それを実行してみると、「Uncaught Error: Class 'GuzzleHttp\Client' not found」と言われます。
❯ php main.php
PHP Fatal error: Uncaught Error: Class 'GuzzleHttp\Client' not found in /Users/suin/Desktop/myapp/main.php:2
Stack trace:
#0 {main}
thrown in /Users/suin/Desktop/myapp/main.php on line 2
Fatal error: Uncaught Error: Class 'GuzzleHttp\Client' not found in /Users/suin/Desktop/myapp/main.php:2
Stack trace:
#0 {main}
thrown in /Users/suin/Desktop/myapp/main.php on line 2
対処法: vendor/autoload.phpをrequireする
この場合、単純にvendor/autoload.phpを読み込むのを忘れているだけなので、読み込むようにします。
<?php
require 'vendor/autoload.php'; // この行を追加
$client = new GuzzleHttp\Client();
composer.jsonにautoloadの定義を忘れていないか?
プロジェクトによってはsrc
ディレクトリにプロジェクトのクラスを格納して、そのパッケージを使うことがあります。そうしたパッケージを名前解決するには、composer.jsonにautoloadディレクティブを宣言しないといけません。
たとえば次のようなautoloadディレクティブの無い状態で、
{
"name": "suin/myapp",
"require": {
"guzzlehttp/guzzle": "^6.3"
}
}
次のプロジェクト独自クラスを、
<?php
namespace MyApp;
class Application
{
}
main.phpなどのクライアントコードで使おうとしても、
<?php
require 'vendor/autoload.php';
$app = new MyApp\Application();
Composerのクラスローダーはクラスを見つけることができず、Fatalエラーになります。
❯ php main.php
PHP Fatal error: Uncaught Error: Class 'MyApp\Application' not found in /Users/suin/Desktop/myapp/main.php:3
Stack trace:
#0 {main}
thrown in /Users/suin/Desktop/myapp/main.php on line 3
Fatal error: Uncaught Error: Class 'MyApp\Application' not found in /Users/suin/Desktop/myapp/main.php:3
Stack trace:
#0 {main}
thrown in /Users/suin/Desktop/myapp/main.php on line 3
対処法: composer.jsonにautoloadディレクティブを追加する
composer.jsonにautoloadディレクティブが追加されているか確認しましょう。
{
"name": "suin/myapp",
"require": {
"guzzlehttp/guzzle": "^6.3"
},
// ここ↓
"autoload": {
"psr-4": {
"MyApp\\": "src/"
}
}
}
そして、それを追加したらcomposer dumpautoload
を実行して、autoload.php関連のファイルを再生成しましょう。
❯ composer dumpautoload
Generating autoload files
vendor/composer/autoload_*.phpの内容が最新になっているか?
チームで開発していてvendorディレクトリをgitignore等でバージョン管理の管理外にしていると、クラスローダーマップが最新でなくなっていることがあります。もし、vendorの中身をバージョン管理しているなら、このチェックは飛ばして構いません。
対処法: composer dumpautoloadでクラスローダーのマップを最新にする
composer dumpautoload
でvendor/composer/autoload_*.phpの内容を最新にしましょう。
❯ composer dumpautoload
Generating autoload files
ちなみに、composer.jsonのautoloadディレクティブでpsr-0やpsr-4などのローディング方法を設定できますが、ここで設定した内容はcomposer dumpautoload
をしてはじめて、vendor/composer/autoload_*.phpのファイル群に反映されます。
たとえば、次のようなcomposer.jsonに対して、
{
"name": "suin/myapp",
"require": {
"guzzlehttp/guzzle": "^6.3"
},
"autoload": {
"psr-4": {
"MyApp\\": "src/"
}
}
}
composer dumpautoload
を実行すると、次のようなマップ情報を生成してくれます。'MyApp\\' => array($baseDir . '/src')
が宣言されているところに注目してください。これはMyApp
パッケージのクラス等をsrc
ディレクトリの中にあるよ、というマップ情報になっています。
<?php
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'),
'MyApp\\' => array($baseDir . '/src'),
'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'),
'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'),
);
スペルミスは無いか?
ありがちなのはクラス名やネームスペースのスペルミスです。
対処法: スペルミスがないかひとつひとつ確認する
- 大文字小文字は合っているか?
- 単数形複数形の間違いはないか?
- タイプミスがないか?
- クラス名とファイル名は同じか?
- パッケージ名とネームスペース名は同じか?
目視確認するだけでなく、クラス名をクラスの定義からクライアントコードにコピペする、クラス定義からクラスファイル名にコピペするなどを繰り返していって確実に間違っていない状況を作って確認してください。目視だけだと見落としがありえます。
いま作業しているディレクトリは実行環境のものか?
今あなたが変更を加えているファイルが、実は実行しているファイルではないかもしれません。変更しているクラスが、実は別プロジェクトの同じ名前のクラスかもしれません。同じプロジェクト内でも、別パッケージの同名クラスかもしれません。タグエディタにはパッケージやパスが隠れているものもあるので、この手のミスはなかなか気づけません。
対処法: エディタとは別の方法(CLI)でダブルチェックする
エディタ上だけで見ていると「全然別のファイル変更してたわー」ということに気がつくまで時間がかかったりするので、まずはファイルシステムにあなたの変更がちゃんと反映されているかを、コマンドラインで二重の確認しましょう。
-
pwd
でPHPを実行している場所が想定している場所か確認しよう。 -
ls
でクラスファイルがあるか確認しよう。 -
cat
やless
で変更がちゃんとファイルシステムに保存されているか確認しよう。
❯ cat src/Application.php
<?php
namespace MyApp; // ネームスペースはあっていますか?
class Application // クラス名はあっていますか?
{
}
最後までお読みくださりありがとうございました。Twitterでは、Qiitaに書かない技術ネタなどもツイートしているので、よかったらフォローお願いします→Twitter@suin