クラスをロードするためのカスタム アルゴリズムがあります。-esがあり$sourcePaths
、オートローダーはその中のすべての .php ファイルを調べ、ファイルからクラス、インターフェースを収集します。次に、連想配列に格納し$classes[class name] => absoule path
ます。後でオートロードが発生すると、クラスが配列内にあるかどうかが調べられ、そうでない場合は、そのクラスは存在しません。これまでのところOKです。しかし、名前空間が登場します。名前空間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;
}