这是作曲家PSR-4自动加载的实现:
localhost:xxxx/something
这是PSR-4文档中的示例:
private function findFileWithExtension($class, $ext)
{
// PSR-4 lookup
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
$first = $class[0];
if (isset($this->prefixLengthsPsr4[$first])) {
$subPath = $class;
while (false !== $lastPos = strrpos($subPath, '\\')) {
$subPath = substr($subPath, 0, $lastPos);
$search = $subPath . '\\';
if (isset($this->prefixDirsPsr4[$search])) {
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
foreach ($this->prefixDirsPsr4[$search] as $dir) {
if (file_exists($file = $dir . $pathEnd)) {
return $file;
}
}
}
}
}
您会发现Composer的实现还有一个额外的判断,即:
protected function loadMappedFile($prefix, $relative_class)
{
// are there any base directories for this namespace prefix?
if (isset($this->prefixes[$prefix]) === false) {
return false;
}
// look through base directories for this namespace prefix
foreach ($this->prefixes[$prefix] as $base_dir) {
// replace the namespace prefix with the base directory,
// replace namespace separators with directory separators
// in the relative class name, append with .php
$file = $base_dir
. str_replace('\\', '/', $relative_class)
. '.php';
// if the mapped file exists, require it
if ($this->requireFile($file)) {
// yes, we're done
return $file;
}
}
// never found it
return false;
}
我不明白为什么要加上这个判断。有人可以告诉我吗?
答案 0 :(得分:0)
首先,这两个函数是脱离上下文使用的,它们的作用截然不同-即使您比较函数参数,也可以看到它们彼此不对应,因此比较它们没有多大意义。
但是Composer实现中的这一附加条件确保了更精确的名称空间优先于更通用的定义。因为通常程序包通常共享相同的根名称空间。例如,在Yii 2 Framework中:
yii2
软件包使用yii
作为所有类的根名称空间,并且源代码位于vendor/yiisoft/yii2
中。yii2-redis
扩展名使用yii\redis
命名空间,源代码位于vendor/yiisoft/yii2-redis
中。在这种情况下,如果要使用yii\redis\Connection
类定义来解析文件,则有两种选择:
vendor/yiisoft/yii2/redis/Connection
,vendor/yiisoft/yii2-redis/Connection
。第二个是正确的。并且由于Composer实施中的这一附加条件,它将被用作首选,因为yii\redis
名称空间的定义比yii
名称空间的定义更为精确。这样,您可以提高自动加载器的性能(但是,如果使用优化的自动加载器则无关紧要),使其更具可预测性,并允许您覆盖某些类(对于新实现,您只需要为文件使用更精确的名称空间)即可。