更新:由于这个答案变得有些流行,我创建了一个packagist包来简化事情。它基本上包含我在这里描述的内容,而无需自己添加类或手动配置。它最终可能支持不仅仅是PSR-4。$appRoot
该软件包可以在这里找到:haydenpierce/class-finder。
$ composer require haydenpierce/class-finder
有关详细信息,请参阅自述文件中的信息。
我对这里的任何解决方案都不满意,所以我最终构建了我的类来处理这个问题。此解决方案要求您:
简而言之,此类尝试根据您在 中定义的命名空间来确定类在文件系统上的实际位置。例如,命名空间中定义的类可在 中找到。这是可以信任的,因为 PSR-4 需要将目录结构映射到命名空间:composer.json
Backup\Test
/home/hpierce/BackupApplicationRoot/src/Test
“命名空间前缀”后面的连续子命名空间名称对应于“基目录”中的子目录,其中命名空间分隔符表示目录分隔符。子目录名称必须与子命名空间名称的大小写匹配。
您可能需要调整以指向包含 的目录。appRoot
composer.json
<?php
namespace Backup\Util;
class ClassFinder
{
//This value should be the directory that contains composer.json
const appRoot = __DIR__ . "/../../";
public static function getClassesInNamespace($namespace)
{
$files = scandir(self::getNamespaceDirectory($namespace));
$classes = array_map(function($file) use ($namespace){
return $namespace . '\\' . str_replace('.php', '', $file);
}, $files);
return array_filter($classes, function($possibleClass){
return class_exists($possibleClass);
});
}
private static function getDefinedNamespaces()
{
$composerJsonPath = self::appRoot . 'composer.json';
$composerConfig = json_decode(file_get_contents($composerJsonPath));
return (array) $composerConfig->autoload->{'psr-4'};
}
private static function getNamespaceDirectory($namespace)
{
$composerNamespaces = self::getDefinedNamespaces();
$namespaceFragments = explode('\\', $namespace);
$undefinedNamespaceFragments = [];
while($namespaceFragments) {
$possibleNamespace = implode('\\', $namespaceFragments) . '\\';
if(array_key_exists($possibleNamespace, $composerNamespaces)){
return realpath(self::appRoot . $composerNamespaces[$possibleNamespace] . implode('/', $undefinedNamespaceFragments));
}
array_unshift($undefinedNamespaceFragments, array_pop($namespaceFragments));
}
return false;
}
}