Laravel psr-4 not autoloading
Asked Answered
P

2

9

I have a Laravel project that works fine locally (Mavericks), but classes under psr-4 aren't loading on our stage server (CentOS). I'm getting a Reflection "class not found" error every time I try composer update, or run an artisan command.

All my app-specific classes are stored in my Laravel project under app/heatherland, eg:

app/heatherland/import/ImportJob.php (file contains HeatherLand\Import\ImportJob)

My composer.json contains this entry:

"autoload": {
    "classmap": [
        "app/commands",
        ...
        "app/database/seeds",
    ],
    "psr-4": {
        "HeatherLand\\": "app/heatherland"
    }
},

Locally, the psr-4 classes are added to the array in vendor/composer/autoload_classmap.php. They're not added to this file on the stage server. If I cut and paste them manually, artisan commands work properly, but the next time I run a composer command, the autoload file is overwritten. The autoload_psr4.php on both local and stage has the following entry, which looks fine to me:

'HeatherLand\\' => array($baseDir . '/app/heatherland'),

Here's is a list of stuff I've tried/checked:

  • The case of the class, folder and file names is consistent and correct.
  • I've been using composer dump-autoload liberally, with and without the -o option
  • I can run composer update with the --no-scripts option fine, but artisan still won't run
  • Folder names are lower-case, and I've tried changing them to reflect case of the namespaces (edit: this never happened, at least not successfully).
  • I've tried removing CamelCase from my namespace (eg, changing it to Heatherland), and there aren't any underscores in any of my folder/filenames.
  • I'm running PHP 5.4.30, and composer is up-to-date. Versions are identical on my local setup and stage server. Laravel 4.1.30.
  • No duplicate composer.phar in either system

Any new advice welcome. At this point, I'd be really happy if I've done something silly.

Puglia answered 26/8, 2014 at 6:46 Comment(2)
The case is not correct. The path is named "import/ImportJob.php", while the class name is uppercase "Import/ImportJob". Either fix the folder name to be identical to the class prefix, or fix the PSR-4 to specifically say "HeatherLand\\Import\\":"app/heatherland/import" for this namespace prefix.Willingham
Ha, I'd tried changing a few folder names already, but apparently I never quite got the full combination of folder name changes and dump-autoload in the right order, or possibly three different terminal windows were too much for my foggy brain to handle. In short: correcting the case on the folder names, then running composer du fixed my problem. Composer update command works, as does artisan. Thanks, Sven! Post a response & I'll happily accept.Puglia
P
17

PSR-4 is indeed super-touchy about case, more so than Laravel itself. Full folder paths and names must be in the same case as the namespaces. The only places the cases don't need to be the same is where there's a reference in the PSR-4 section of composer.json.

This only becomes a problem with case-specific operating systems. I had no problems on my Mac, but CentOS refused to play.

Note this is different to the practice used for Laravel-specific framework across its documentation, which uses lowercase folder paths and CamelCase namespaces. This won't cause any problems on any operating system. July 2015 ETA: this info applied to Laravel 4; looks like Laravel 5 default folder structure adheres to psr-4 standards.

I eventually ended up with a folder structure like:

app/heatherland
  Import
    ImportJob.php

namespaces eg

HeatherLand\Import

and a composer.json entry as per the original question:

"autoload": {
    "classmap": [
        "app/commands",
        ...
        "app/database/seeds",
    ],
    "psr-4": {
        "HeatherLand\\": "app/heatherland"
    }
},

Note to self: Remember to run composer dump-autoload. Dump early, dump often.

Puglia answered 4/10, 2014 at 23:40 Comment(2)
Just ran into this issue and found this question. I also found the paragraph in the PSR-4 spec that directly addresses this: The contiguous sub-namespace names after the "namespace prefix" correspond to a subdirectory within a "base directory", in which the namespace separators represent directory separators. The subdirectory name MUST match the case of the sub-namespace names.Heller
changing the folder name from uppercase to lowercase solve the problem of loading the class without the -o flag on composer dump-autoload. Can you explain the reason?Paphian
Q
2

Namespaces, folders and file names are case sensitive.

If you have 'App\website' you must call it in php file 'App\website' is correct but 'App\Website' is wrong

Quattlebaum answered 25/7, 2020 at 16:7 Comment(3)
This has already been answered nearly six years ago - is there anything new you want to highlight?Nester
when using composer 2 it show same warning and this is my experience..Quattlebaum
So, there is nothing new you want to add?Nester

© 2022 - 2024 — McMap. All rights reserved.