В чем разница между инструментом автозагрузки PSR-4 и примером из документа PSR-4? - PullRequest
0 голосов
/ 06 сентября 2018

Это реализация автозагрузки композитора 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;
}

Вы обнаружите, что реализация изКомпозитор имеет дополнительное суждение, а именно:

if (isset($this->prefixLengthsPsr4[$first])) {
    // ...
}

Я не могу понять, почему следует добавить суждение.Может кто-нибудь сказать мне?

1 Ответ

0 голосов
/ 13 ноября 2018

Во-первых, эти две функции вырваны из контекста и делают совершенно разные вещи - даже если вы сравниваете параметры функции, вы можете видеть, что они не соответствуют друг другу, поэтому сравнивать их не имеет особого смысла.

Но это дополнительное условие в реализации Composer гарантирует, что более точное пространство имен имеет приоритет над более общим определением. Потому что в общем случае пакеты часто используют одно и то же корневое пространство имен. Например, в Yii 2 Framework:

  • yii2 с базовой платформой использует yii в качестве корневого пространства имен для всех классов, а исходный код находится в vendor/yiisoft/yii2.
  • yii2-redis использует пространство имен yii\redis, а исходный код находится в vendor/yiisoft/yii2-redis.

В этом случае, если вы хотите разрешить файл с определением класса yii\redis\Connection, у вас есть два варианта:

  1. vendor/yiisoft/yii2/redis/Connection
  2. vendor/yiisoft/yii2-redis/Connection.

Второй правильный. И благодаря этому дополнительному условию в реализации Composer оно будет использоваться в качестве первого выбора, поскольку определение для пространства имен yii\redis является более точным, чем для пространства имен yii. Таким образом, вы можете повысить производительность автозагрузчика (однако это не имеет значения, если вы используете оптимизированный автозагрузчик), сделать его более предсказуемым и позволяет переопределять некоторые классы (вам просто нужно использовать более точное пространство имен для файла с новой реализацией).

...