0

我有一个自定义算法来加载类。有$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;
}
4

0 回答 0