Article

Manual Includes to Composer Autoloading

Stage a migration from require/include trees to Composer classmap and PSR-4 without deleting every include on day one.

Pre-Composer PHP apps often load classes by scanning directories in a custom bootstrap or by listing dozens of require_once lines. That pattern breaks when two files define the same class, when paths differ between CLI and web, or when a new developer cannot find where a symbol is loaded. Autoloading fixes discovery—but ripping out every include overnight is how you create undeclared load-order bugs.

What should become autoloaded

  • Class and interface definitions (PSR-4 or classmap)
  • Traits and enums once the runtime supports them
  • Library code you currently copy into lib/ that has a Composer package equivalent

Not everything is a class. Config arrays, procedural helpers that run side effects on include, and one-off scripts may stay as explicit requires until you refactor them. Do not imply every include must disappear.

LEGACY — include tree
TRANSITIONAL — classmap + keep includes
{
  "autoload": {
    "classmap": ["lib/"],
    "files": ["lib/helpers.php"]
  }
}
MODERN — PSR-4 for new and migrated code
{
  "autoload": {
    "psr-4": {
      "App\\": "src/"
    },
    "files": ["src/helpers.php"]
  }
}

Staged migration that stays safe

  1. Add Composer and require vendor/autoload.php at the top of every entry point (web, CLI, cron).
  2. Register a classmap over the existing lib/ tree; run composer dump-autoload -o.
  3. Remove require_once lines only for classes that the classmap already loads—one directory at a time.
  4. Move new code under src/ with namespaces and PSR-4; stop growing the classmap for new work.
  5. Gradually rename and namespace hot classes; keep a dual period where both paths work under tests.

Load-order traps

Procedural files that define functions or constants on include are not interchangeable with classmaps. Put those in Composer autoload.files, or keep an explicit require until you convert them to namespaced functions or classes.

Verification checklist

  • Hit every entry point after removing a batch of requires
  • Run CLI/cron with the same autoload.php as FPM
  • Search for class_exists / file_exists loaders that bypass Composer
  • Validate mappings with the PSR-4 Checker and Composer.json Validator

Related: Composer center, PSR-4 guide, Adding Composer.

Related reading