composer/class-map-generator
Generate PHP class maps by scanning directories to map classes/interfaces/traits/enums to file paths. Use a simple static helper or an advanced generator to scan multiple paths, sort results, and detect ambiguous class resolutions.
Installation:
composer require composer/class-map-generator
Ensure your project uses PHP 7.2+ (compatible with Laravel 5.8+).
First Use Case:
Generate a class map for a directory (e.g., app/):
use Composer\ClassMapGenerator\ClassMapGenerator;
$map = ClassMapGenerator::createMap(__DIR__ . '/app');
foreach ($map as $class => $path) {
// Log or process discovered classes (e.g., validate PSR compliance)
file_put_contents('classmap.log', "$class => $path\n", FILE_APPEND);
}
Where to Look First:
ClassMapGenerator: Core class for scanning paths and generating maps.ClassMap: Result object with methods like getMap(), sort(), and getAmbiguousClasses().bootstrap/app.php or a custom composer.json script (see Implementation Patterns).Use Case: Optimize autoloading in production (e.g., serverless, high-traffic APIs). Pattern:
composer.json):
{
"scripts": {
"post-autoload-dump": [
"Composer\\ClassMapGenerator\\ClassMapGenerator::generateMap(__DIR__ . '/app', __DIR__ . '/bootstrap/cache/classmap.php')"
]
}
}
// bootstrap/generate-classmap.php
use Composer\ClassMapGenerator\ClassMapGenerator;
$generator = new ClassMapGenerator();
$generator->scanPaths(__DIR__ . '/app');
$generator->scanPaths(__DIR__ . '/vendor/your-package');
$generator->getClassMap()->sort();
file_put_contents(__DIR__ . '/bootstrap/cache/classmap.php', '<?php return ' . var_export($generator->getClassMap()->getMap(), true) . ';');
bootstrap/app.php:
$classMap = require __DIR__ . '/cache/classmap.php';
spl_autoload_register(function ($class) use ($classMap) {
if (isset($classMap[$class])) {
require $classMap[$class];
}
});
Use Case: Catch namespace violations during CI/CD. Pattern:
$generator = new ClassMapGenerator();
$generator->scanPaths(__DIR__ . '/app');
$classMap = $generator->getClassMap();
$violations = $classMap->getPsrViolations();
if (!empty($violations)) {
throw new \RuntimeException("PSR violations found:\n" . implode("\n", $violations));
}
Use Case: Skip test files or fixtures from production maps. Pattern:
$generator = new ClassMapGenerator();
$generator->scanPaths(__DIR__ . '/app', ['exclude' => ['tests', 'fixtures']]);
Use Case: Debug duplicate class names (e.g., User in App\User and Modules\User).
Pattern:
$generator = new ClassMapGenerator();
$generator->scanPaths(__DIR__ . '/app');
$generator->scanPaths(__DIR__ . '/modules');
$classMap = $generator->getClassMap();
foreach ($classMap->getAmbiguousClasses() as $class => $paths) {
error_log("Ambiguous class '$class' found in: " . implode(', ', $paths));
}
Use Case: Scan remote paths (e.g., S3, Git repos) via s3:// or git:// wrappers.
Pattern:
$generator = new ClassMapGenerator();
$generator->scanPaths('s3://your-bucket/path/to/code');
Replace Laravel’s default composer dump-autoload --optimize with a custom script:
composer dump-autoload --no-dev
php bootstrap/generate-classmap.php
Pros:
For modular apps (e.g., plugins, themes):
// In PluginManager.php
public function loadClasses(Plugin $plugin) {
$generator = new ClassMapGenerator();
$generator->scanPaths($plugin->getPath());
$classMap = $generator->getClassMap();
foreach ($classMap->getMap() as $class => $path) {
if (str_starts_with($class, $plugin->getNamespace())) {
$this->registerClass($class, $path);
}
}
}
Combine with spl_autoload_register for hybrid static/dynamic loading:
$classMap = require __DIR__ . '/cache/classmap.php';
spl_autoload_register(function ($class) use ($classMap) {
if (isset($classMap[$class])) {
require $classMap[$class];
}
});
// Fallback to Composer autoloader
spl_autoload_register();
Ambiguous Classes:
app/ + vendor/) may produce duplicate class names.getAmbiguousClasses() to debug and manually resolve conflicts. Exclude problematic directories if possible.PSR Violations:
getPsrViolations() in CI to fail builds early. Example:
$violations = $classMap->getPsrViolations();
if (!empty($violations)) {
exit(1); // Fail CI
}
Windows Paths:
C:\path\to\file.php).realpath() or ensure paths are forward-slash normalized:
$generator->scanPaths(str_replace('\\', '/', __DIR__ . '/app'));
Stream Wrapper Quirks:
s3://).allow_url_fopen is enabled or use php://filter wrappers as a fallback.Performance with Large Codebases:
ClassMapGenerator::createMap() for one-off scans.Aliased Use Statements:
use Foo\Bar as Baz; may cause parsing errors.PHP 8.4+ Nullability:
Log Warnings:
$classMap = $generator->getClassMap();
foreach ($classMap->getWarnings() as $warning) {
error_log($warning);
}
Inspect Raw Data:
$map = $generator->getClassMap()->getMap();
print_r(array_slice($map, 0, 10)); // Show first 10 entries
Validate Against Composer:
Compare output with composer dump-autoload --no-dev --classmap-only:
composer dump-autoload --no-dev --classmap-only > composer-classmap.php
php -r '$map = require "composer-classmap.php"; print_r(array_keys($map));'
Custom Filters:
Extend ClassMapGenerator to filter classes by namespace or regex:
$generator = new ClassMapGenerator();
$generator->scanPaths(__DIR__ . '/app');
$filteredMap = array_filter($generator->getClassMap()->getMap(), function ($class) {
return str_starts_with($class, 'App\\');
}, ARRAY_FILTER_USE_KEY);
Post-Processing:
Use ClassMap::sort()
How can I help you explore Laravel packages today?