问题
I'm using composer to generate autoloader:
"autoload": {
"psr-4": {
"SomeNamespace\\": "src/SomeDir"
}
}
I need to create instances of all classes that implement specific interface. It's fairly easy when not using autoloader, however get_declared_classes()
is not playing well with autoloaders. It will list a class only after it was instantiated with autoloader.
回答1:
If you don't keep track of which classes exist, autoloading won't help you.
But the situation would be pretty much the same if you tried to include all files and see which classes would come out of it, when there would be a chance that you missed a file.
Whatever it is what you try to do: Try it differently. I highly doubt you have to instantiate ALL these classes when serving one single request. It would not be very beneficial to the performance if you had to scan ALL declared classes for an interface, and then create an instance for all of them.
Provide some kind of registering method to let the application know about your classes. If you really have to use them all, so be it. But scanning whatever code has been run previously does not sound right (and you didn't explain what you do at all).
回答2:
You can use dirty hack and require_once
all classes before get_declared_classes()
function call.
- At first do dump all classes to class map via
composer dumpautoload --optimize
- Now you can fetch composer loader and require all files
$res = get_declared_classes();
$autoloaderClassName = '';
foreach ( $res as $className) {
if (strpos($className, 'ComposerAutoloaderInit') === 0) {
$autoloaderClassName = $className; // ComposerAutoloaderInit323a579f2019d15e328dd7fec58d8284 for me
break;
}
}
$classLoader = $autoloaderClassName::getLoader();
foreach ($classLoader->getClassMap() as $path) {
require_once $path;
}
- Now you can easy use
get_declared_classes()
again, which return all classes the composer knowns
P.S. Don't use it in production.
回答3:
I had similar use case for all *Sniff.php
classes found in some directory.
You can use Nette\RobotLoader.
Snippets from my app for inspiration: RobotLoaderFactory + Getting all the classes
And for your use case:
$src = __DIR__ . '/src';
$robotLoader = new Nette\Loaders\RobotLoader\RobotLoader;
$robotLoader->setTempDirectory(__DIR__ . '/temp');
$robotLoader->addDirectory($src);
$robotLoader->acceptFiles = ['*Suffix.php']; // optional to reduce file count
$robotLoader->rebuild();
$foundClasses = array_keys($robotLoader->getIndexedClasses());
// filter in any way
来源:https://stackoverflow.com/questions/36676074/php-how-to-get-all-classes-when-using-autoloader