composer-php - Composer PSR-4自动加载的实现与PSR-4文档中的示例有什么区别
问题描述
这是 composer 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;
}
}
}
}
}
这是 PSR-4 文档中的示例:
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;
}
你会发现Composer的实现多了一个判断,即:
if (isset($this->prefixLengthsPsr4[$first])) {
// ...
}
我不明白为什么要添加判断。有人可以告诉我吗?
解决方案
首先,这两个函数脱离了上下文,做了完全不同的事情——即使你比较函数参数,你也可以看到它们并不对应,所以比较它们没有多大意义。
但是 Composer 实现中的这个附加条件确保了更精确的命名空间优先于更一般的定义。因为通常包通常共享相同的根命名空间。例如在 Yii 2 框架中:
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
。通过这种方式,您可以提高自动加载器的性能(但如果您使用优化的自动加载器则无关紧要),使其更可预测并允许您覆盖某些类(您只需要为具有新实现的文件使用更精确的命名空间)。
推荐阅读
- xcode - 如何在 Xcode 中轻松复制文件名和类似“filename:line”的行?
- parsing - LR(1) 解析器 - 制作内联产品
- c++ - c ++如何评估函数列表?
- javascript - 为项目构建我的 mongoDB 并访问嵌套数组
- cross-compiling - 在 ubuntu 20 上编译内核 3.xx
- r - 在装扮的 SVM 函数上调整参数时出现未使用的参数错误
- c - 构建带有负节点的表达式树
- python - 从 10 个输出到 25 个输出 CNN,但修改后的代码不起作用?
- python - 需要 Cpanel SQLite 3.8.3 或更高版本(找到 3.7.17)
- javascript - 在 ReactJS 中获取 onComponentDidMount 期间出现 CORS 错误