composer/class-map-generator
Generate PHP class maps by scanning directories for classes, interfaces, traits, and enums. Create a quick symbol-to-file map or use the generator for multi-path scans, sorting, and reporting ambiguous class definitions. MIT licensed; PHP 7.2+.
Installation:
composer require composer/class-map-generator
Requires PHP 7.2+ (compatible with Laravel 7+).
First Use Case:
Generate a class map for a directory (e.g., Laravel’s app/):
use Composer\ClassMapGenerator\ClassMapGenerator;
$map = ClassMapGenerator::createMap(app_path());
foreach ($map as $class => $path) {
// Use $class and $path (e.g., log, cache, or validate)
}
Where to Look First:
ClassMapGenerator: Core class for scanning paths and generating maps.ClassMap: Result object with methods like getMap(), getAmbiguousClasses(), and sort().Use createMap() for ad-hoc discovery (e.g., CLI tools, migrations):
$map = ClassMapGenerator::createMap(base_path('plugins'));
// Process $map directly (no generator object needed).
Scan multiple paths (e.g., Laravel modules, plugins) and merge results:
$generator = new ClassMapGenerator();
$generator->scanPaths(app_path('Modules'));
$generator->scanPaths(app_path('Plugins'));
$classMap = $generator->getClassMap();
Integrate with SplAutoloader or Laravel’s ClassLoader:
$map = ClassMapGenerator::createMap(storage_path('dynamic'));
foreach ($map as $class => $path) {
if (!class_exists($class, false)) {
require $path;
}
}
Validate namespaces against a base prefix (e.g., App\Modules\):
$generator = new ClassMapGenerator();
$generator->setBaseNamespace('App\\Modules\\');
$generator->scanPaths(app_path('Modules'));
$classMap = $generator->getClassMap();
foreach ($classMap->getPsrViolations() as $violation) {
// Log or fix violations (e.g., missing namespace).
}
Detect and resolve duplicate class names (e.g., User in App and Vendor):
$generator->scanPaths([app_path(), vendor_path()]);
$classMap = $generator->getClassMap();
foreach ($classMap->getAmbiguousClasses() as $class => $paths) {
// Log or prioritize paths (e.g., prefer `app/` over `vendor/`).
}
Artisan Commands/Migrations:
Pre-generate class maps in boot() or handle() to avoid autoloading:
protected function handle()
{
$map = ClassMapGenerator::createMap(app_path('Features'));
// Cache $map for subsequent runs.
}
Service Providers:
Register a custom autoloader in register():
public function register()
{
$loader = new \Composer\Autoload\ClassLoader();
$map = ClassMapGenerator::createMap(app_path('Extensions'));
$loader->addClassMap($map);
$loader->register();
}
CI/CD Optimization: Cache class maps in GitHub Actions:
# .github/workflows/test.yml
jobs:
test:
steps:
- uses: actions/cache@v3
with:
path: ~/.cache/class-maps
key: ${{ runner.os }}-class-maps
- run: php artisan class-map:generate --cache
Dynamic Plugin Loading:
Scan a plugins/ directory at runtime:
public function loadPlugins()
{
$generator = new ClassMapGenerator();
$generator->scanPaths(storage_path('plugins'));
$classMap = $generator->getClassMap();
foreach ($classMap->getMap() as $class => $path) {
if (str_starts_with($class, 'Plugin\\')) {
$this->registerPlugin($class);
}
}
}
Combine with Laravel’s ClassLoader:
Merge generated maps with Laravel’s autoloader:
$loader = require base_path('vendor/autoload.php');
$loader->addClassMap(ClassMapGenerator::createMap(app_path('Custom')));
Cache Results:
Serialize ClassMap to JSON/cache:
$map = ClassMapGenerator::createMap(app_path());
file_put_contents(cache_path('class-map.json'), json_encode($map));
Exclude Directories: Skip tests/fixtures:
$generator->scanPaths(app_path(), ['excludes' => ['tests', 'fixtures']]);
Stream Wrapper Support: Scan remote paths (e.g., S3, SFTP):
$generator->scanPaths('s3://bucket/path');
Ambiguous Classes:
app/ + vendor/) may yield duplicate class names (e.g., User).getAmbiguousClasses() to resolve conflicts or exclude paths:
$generator->scanPaths(app_path());
$generator->scanPaths(vendor_path('laravel/framework'));
$ambiguous = $generator->getClassMap()->getAmbiguousClasses();
PSR Violations:
$generator->setBaseNamespace('App\\');
$violations = $generator->getClassMap()->getPsrViolations();
Performance:
vendor/) is slow.scanPaths() incrementally (e.g., scan app/ first, then vendor/).tests, node_modules).Windows Paths:
realpath() or ensure paths are absolute:
$generator->scanPaths(realpath(app_path()));
Stream Wrappers:
allow_url_fopen is enabled.Dynamic Classes:
eval(), create_function()) won’t appear in maps.Enums and Modern PHP:
Inspect Warnings:
getClassMap()->getWarnings() to debug scanning issues.Log Ambiguous Classes:
foreach ($classMap->getAmbiguousClasses() as $class => $paths) {
Log::warning("Ambiguous class {$class}: " . implode(', ', $paths));
}
Validate Paths:
if (!file_exists($path)) {
throw new \RuntimeException("Path {$path} does not exist.");
}
Check PHP Version:
php -v or PHP_VERSION_ID >= 70200).Sorting:
$classMap->sort();
Exclude Patterns:
$generator->scanPaths(app_path(), [
'excludes' => ['*Test.php', 'Resources/views'],
'includes' => ['*Service.php']
]);
Combine with Laravel:
AppServiceProvider@boot() to pre-load critical classes:
public function boot()
{
$map = ClassMapGenerator::createMap(app_path('Core
How can I help you explore Laravel packages today?