◀ 20.

【Laravelエラー】does not comply with psr-4 autoloading standard. Skipping.

この記事の要点
  • Composer がオートロード情報を作るときに、PSR-4 の規則に合わないクラスを見つけて読み込み対象から外したという警告
  • 規則は「namespace = ディレクトリ階層」「クラス名 = ファイル名」。大文字・小文字も一致が必要
  • 例: App\Models\User は app/Models/User.php に置く
  • Composer 1 では黙って読み込めていたものが Composer 2 で警告になったため、「昔は動いていた」が起きやすい
  • 直したら composer dump-autoload を再実行し、警告が消えたことを確認する

エラー内容

Class App\Model\User located in ./app/Models/User.php does not comply with psr-4 autoloading standard. Skipping.

「./app/Models/User.php にある App\Model\User クラスは PSR-4 オートロード規約に従っていないので、スキップします」という意味です。メッセージにはクラス名(namespace 付き)とファイルの場所が両方出ているので、その 2 つを見比べるのが解決の近道です。

発生条件

Laravel などで、次のような Composer のコマンドを実行したときに表示されます。

composer dump-autoload
composer install
composer update

警告が出たクラスはオートロードの対象から外れるため、そのクラスを使う処理で Class "App\Model\User" not found などのエラーが後から発生します。

原因: PSR-4 の規則とずれている

PSR-4 は、クラスの完全修飾名からファイルの場所を機械的に決める規約です。Laravel の composer.json には、標準で次のような対応が書かれています。

"autoload": {
    "psr-4": {
        "App\\": "app/",
        "Database\\Factories\\": "database/factories/",
        "Database\\Seeders\\": "database/seeders/"
    }
}

この設定では、App\ の後ろの namespace がそのまま app/ の下のディレクトリ階層になり、最後のクラス名がファイル名になります。

クラス名正しいファイルの場所判定
App\Model\Userapp/Model/User.phpOK
App\Model\Userapp/Models/User.php に置いたNG(ディレクトリ名が違う)
App\Models\Userapp/models/User.php に置いたNG(大文字・小文字が違う)
App\Http\Controllers\Admin\UserControllerapp/Http/Controllers/Admin/UserController.phpOK
App\Http\Controllers\UserControllerapp/Http/Controllers/UsersController.php に置いたNG(ファイル名が違う)

つまり、App\Model\User を使う場合は、ディレクトリとファイル名を同様のものにしなければなりません。app\Model\User.php なら OK で、app\Models\User.php の場合は NG です。

「昔は動いていたのに」となる理由

  • Composer 2 で厳しくなった: Composer 1 では、規則に合わないクラスもクラスマップ生成時に読み込まれてしまうことがありました。Composer 2 からは、こうしたクラスを警告付きでスキップするようになりました。Composer をアップデートしただけで突然この警告が出るのはこのためです
  • Laravel 8 でディレクトリ構成が変わった: モデルの標準の置き場所が app/ 直下から app/Models/ に、シーダーが database/seeds から namespace 付きの database/seeders に変わりました。古いプロジェクトをアップグレードする途中で、ファイルだけ移動して namespace を直し忘れると、この警告になります
  • Windows では動いて Linux で動かない: Windows のファイルシステムは大文字・小文字を区別しないため、models と Models の違いが手元では問題にならず、Linux の本番環境で初めて発覚することがあります

対処法

  1. 警告メッセージのクラス名とファイルの場所を見比べ、どちらを正とするか決めます(Laravel 8 以降のモデルなら App\Models + app/Models/ が標準)
  2. ファイル先頭の namespace 宣言、またはファイルの置き場所・ファイル名を、規則どおりに揃えます
  3. namespace を変えた場合は、そのクラスを use している箇所(コントローラー、config/auth.php のモデル指定など)も新しい名前に直します
  4. 1 ファイルに 1 クラスだけを書きます。1 ファイルに複数クラスがあると、ファイル名と一致しないクラスは読み込まれません
  5. オートロード情報を作り直します
<?php
// app/Models/User.php

namespace App\Models;   // ディレクトリ app/Models と一致させる

use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable   // クラス名とファイル名 User.php を一致させる
{
    // ...
}
composer dump-autoload

確認方法

  • composer dump-autoload を実行して、does not comply with psr-4 の行が 1 つも出なければ解決です
  • php artisan tinker で class_exists(App\Models\User::class) を実行し、true が返るか確認します
  • CI で継続的にチェックしたい場合、比較的新しい Composer 2 には、違反があると失敗扱いにする composer dump-autoload --strict-psr があります(使える版かは composer dump-autoload --help で確認してください)

関連

子ページ

子ページはありません

同階層のページ
  1. SQLSTATE[HY000] [1045] Access denied for user 'homestead'@'localhost'
  2. Add [~] to fillable property to allow mass assignment on [App\~].
  3. PHP Parse error: syntax error, unexpected 'class' (T_CLASS), expecting identifier (T_STRING) or variable (T_VARIABLE) or '{' or '$' in ~
  4. Changing columns for table "~" requires Doctrine DBAL; install "doctrine/dbal"
  5. MethodNotAllowedHttpException No message
  6. Class 'Doctrine\DBAL\Driver\PDOMySql\Driver' not found
  7. production.ERROR: No application encryption key has been specified.
  8. Dotenv values containing spaces must be surrounded by quotes.
  9. Laravel \ Socialite \ Two \ InvalidStateException
  10. The page has expired due to inactivity. Please refresh and try again.
  11. Failed to clone https://github.com/symfony/thanks.git via https, ssh protocol
  12. Illegal offset type
  13. Cannot access protected property Illuminate\Http\Request::$...
  14. Emitted value instead of an instance of Error
  15. 画像保存時にInternal Server Error
  16. Failed to authenticate on SMTP server with username ...
  17. PostTooLargeException
  18. Database hosts array is empty.
  19. Invalid request (Unsupported SSL request)
  20. does not comply with psr-4 autoloading standard. Skipping.
  21. MySQLのSTR_TO_DATE関数を使用するとnullが返却される問題