Introduction
Composer generates an autoload map (vendor/composer/autoload_*.php) that maps class names to file paths. When you add new classes, the autoload map is not updated automatically until you run composer dump-autoload. In production with --optimize or classmap authorization, the old cached autoload map does not know about the new classes, causing Class not found errors even though the files exist.
Symptoms
Fatal error: Uncaught Error: Class 'App\Service\NewService' not found- Class file exists but PHP cannot find it
- Works after
composer dump-autoloadbut breaks again on next deploy - Works in development but fails in production
composer installon production does not pick up new classes
PHP Fatal error: Uncaught Error: Class "App\Service\PaymentGateway" not found
in /var/www/html/src/Controller/CheckoutController.php:45
Stack trace:
#0 /var/www/html/public/index.php(12): CheckoutController->process()Common Causes
- New files added without running
composer dump-autoload - Deployment script not running autoload regeneration
- PSR-4 namespace path mismatch
- Classmap-optimized autoload not including new directories
- Files in non-standard locations not covered by autoload rules
Step-by-Step Fix
- 1.Regenerate autoload files:
- 2.```bash
- 3.# Regenerate autoload (development)
- 4.composer dump-autoload
# Regenerate with optimization (production - faster) composer dump-autoload --optimize
# Regenerate with classmap for even faster loading composer dump-autoload --optimize --classmap-authoritative
# Verify the class is in the autoload map grep -r "PaymentGateway" vendor/composer/autoload_*.php ```
- 1.Verify PSR-4 namespace configuration:
- 2.```json
- 3.// composer.json
- 4.{
- 5."autoload": {
- 6."psr-4": {
- 7."App\\": "src/"
- 8.}
- 9.}
- 10.}
// File structure must match: // src/Service/PaymentGateway.php -> namespace App\Service; class PaymentGateway
// WRONG - namespace does not match directory // src/Services/PaymentGateway.php with namespace App\Service; // (Services vs Service - plural mismatch)
// CORRECT - namespace matches directory exactly // src/Service/PaymentGateway.php with namespace App\Service; ```
- 1.Add classmap for non-PSR-4 files:
- 2.```json
- 3.// composer.json
- 4.{
- 5."autoload": {
- 6."psr-4": {
- 7."App\\": "src/"
- 8.},
- 9."classmap": [
- 10."src/Legacy/",
- 11."src/Helpers/"
- 12.],
- 13."files": [
- 14."src/functions.php"
- 15.]
- 16.}
- 17.}
// Then regenerate composer dump-autoload --optimize ```
- 1.Fix deployment script to regenerate autoload:
- 2.```bash
- 3.#!/bin/bash
- 4.# deploy.sh
# Install/update dependencies composer install --no-dev --optimize-autoloader --no-interaction
# Verify critical classes are autoloadable php -r "new App\Service\PaymentGateway();" || { echo "ERROR: PaymentGateway class not found!" exit 1 }
echo "Deployment autoload verified" ```
- 1.Debug autoload resolution:
- 2.```bash
- 3.# Show what Composer knows about a class
- 4.composer show --path | grep "your-package"
# Find the actual autoload mapping php -r " require 'vendor/autoload.php'; \$reflector = new ReflectionClass('App\Service\PaymentGateway'); echo \$reflector->getFileName(); "
# If class is not found, check the autoload files directly cat vendor/composer/autoload_classmap.php | grep -i payment ```
Prevention
- Always run
composer dump-autoload --optimizeafter adding new classes - Include autoload regeneration in deployment scripts
- Use PSR-4 autoloading (not classmap) for new code - it does not require regeneration
- Run
composer validateto check composer.json for autoload errors - Add a post-deploy smoke test that instantiates critical classes
- Use
composer install --optimize-autoloaderin CI/CD pipelines - Never commit
vendor/composer/autoload_*.phpfiles to version control