PHP: How to get all classes when using autoloader

◇◆丶佛笑我妖孽 提交于 2020-01-02 06:33:29

问题


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.

  1. At first do dump all classes to class map via composer dumpautoload --optimize
  2. 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;
    }
  1. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!