I’m working on a code generator, and would like to get the path to a namespace.
That is, given namespace ‘AppController’, I’d like to get "src/Controller".
I see how to get that information using ReflectionClass if I already had the class, but in this case I don’t have it yet.
My solution at the application level is to simply read composer.json and look for the autload section. But that won’t work with bundles (e.g. namespace AcmeApiBundle -> vendor/acme/api-bundle’). I imagine there’s an autoload map somewhere, but I can’t find how to access it.
FWIW, I’m using Symfony, but I don’t think that’s going to matter here. More importantly, I’m using composer and psr-4 autloaded namespaces/classes.
Thanks.
2
Answers
In the end, the mapping file I was looking for is found in vendor/composer/autoload_psr4.php, and I was able to do the mapping by reading it and traversing the map.
The "path to a namespace" does not necessarily exist as the mapping between class name, namespace and all, can point literally anywhere. Only in the specific case of a PSR4-compliant autoloader does a namespace have any significance in that the there is a "root" directory that represents an arbitrary prefix of the namespace, and subdirectories/files representative of the rest of the class name. Any other type of autoloader [eg: classmap] will not necessarily have any relation between class name and file path.
Further to that, even in the case of a PSR4-compliant autoloader the specific function of a given autoloader may well prevent any dynamically-generated code from being picked up, eg: calling composer with
-o / --optimize-autloader
will cause Composer to scan its autoload directories for classes and generate a static classmap, so anything that you were to add there would not be picked up until you re-generated the classmap and restarted execution. While not the default,-o
is a strongly-recommended and widely-used optimization.A better solution would be to define your own custom autoloader and use
spl_autoload_register()
to append it to the autoloader queue after the composer autoloader. If you want your class to override something coming from composer you would want to use the$prepend
argument.Other related caveats:
vendor/
directory is a generally not a good idea as that directory should be considered ephemeral and composer operations can and will erase any changes.