我有自定义算法来加载类。有$sourcePaths
- es,自动加载器查找其中的所有.php文件,并从文件中收集类,接口。然后它存储在关联数组$classes[class name] => absoule path
中。稍后,当自动加载发生时,它会查看该类是否在数组中,如果不存在该类则不存在。
到目前为止还可以。但这里有名称空间。让我们看一个命名空间Doctrine\ORM\Query;
和一个类Parameter { .... }
的情况。首先,我只是处理它,因为它是Doctrine \ ORM \ Query \ Parameter ...所以命名空间+类名。但是后来还有一个new Query\Parameter
仍未找到。什么是在命名空间内查找类的正确算法?
收集的课程:
foreach ($sourcePaths as $dir)
{
foreach (new DirectoryIterator($dir) as $fileinfo)
{
if (substr($fileinfo->getFilename(), -4) == '.php')
{
$absPath = str_replace('\\', '/', $dir.'/'.$fileinfo->getFilename());
foreach (getPhpClasses($absPath) as $item)
{
$autoloadClassPaths[$item] = $absPath;
}
}
}
}
这个函数从php代码中获取东西:
function getPhpClasses ($filename)
{
$output = array();
$namespace = '';
$tokens = token_get_all(file_get_contents($filename));
for ($i = 2; $i < sizeof($tokens); $i++)
{
if (($tokens[$i - 2][0] == T_NAMESPACE) && $tokens[$i - 1][0] == T_WHITESPACE && $tokens[$i][0] == T_STRING)
{
$j = 0;
do
{
$namespace .= $tokens[$i + $j][1];
$j++;
} while ($tokens[$i + $j] != ';');
$namespace .= '\\';
}
if (($tokens[$i - 2][0] == T_CLASS || $tokens[$i - 2][0] == T_INTERFACE) && $tokens[$i - 1][0] == T_WHITESPACE && $tokens[$i][0] == T_STRING)
{
$output[] = $namespace.$tokens[$i][1];
}
}
return $output;
}