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-autoload but breaks again on next deploy
  • Works in development but fails in production
  • composer install on production does not pick up new classes
bash
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. 1.Regenerate autoload files:
  2. 2.```bash
  3. 3.# Regenerate autoload (development)
  4. 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. 1.Verify PSR-4 namespace configuration:
  2. 2.```json
  3. 3.// composer.json
  4. 4.{
  5. 5."autoload": {
  6. 6."psr-4": {
  7. 7."App\\": "src/"
  8. 8.}
  9. 9.}
  10. 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. 1.Add classmap for non-PSR-4 files:
  2. 2.```json
  3. 3.// composer.json
  4. 4.{
  5. 5."autoload": {
  6. 6."psr-4": {
  7. 7."App\\": "src/"
  8. 8.},
  9. 9."classmap": [
  10. 10."src/Legacy/",
  11. 11."src/Helpers/"
  12. 12.],
  13. 13."files": [
  14. 14."src/functions.php"
  15. 15.]
  16. 16.}
  17. 17.}

// Then regenerate composer dump-autoload --optimize ```

  1. 1.Fix deployment script to regenerate autoload:
  2. 2.```bash
  3. 3.#!/bin/bash
  4. 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. 1.Debug autoload resolution:
  2. 2.```bash
  3. 3.# Show what Composer knows about a class
  4. 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 --optimize after 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 validate to check composer.json for autoload errors
  • Add a post-deploy smoke test that instantiates critical classes
  • Use composer install --optimize-autoloader in CI/CD pipelines
  • Never commit vendor/composer/autoload_*.php files to version control