ClassLoader.php в Cotonti
позволяет динамически загружать классы и интерфейсы по мере их использования, без необходимости вручную подключать файлы с классами через require или include.
Файл ClassLoader.php в контексте системы Cotonti CMF является частью автозагрузчика классов, реализованного в рамках Composer. Он находится в директории /lib/vendor/composer/ и отвечает за управление автозагрузкой классов и интерфейсов в проекте.
Основное назначение и место в системе Cotonti:
ClassLoader.php реализует механизм автозагрузки, который позволяет динамически загружать классы и интерфейсы по мере их использования, без необходимости вручную подключать файлы с классами через require или include. Он интегрирован с системой Composer, которая управляет зависимостями и помогает организовать правильную загрузку классов из различных пространств имен (namespaces) или классов, использующих стандарты PSR-4 и PSR-0.
Взаимодействие внутри сайта:
Этот файл взаимодействует с основной логикой Cotonti через систему автозагрузки классов. Когда Cotonti пытается использовать какой-либо класс, который ещё не был загружен, механизм автозагрузки срабатывает и находит соответствующий файл с классом, включая его в работу. Важнейший аспект — это то, что все классы, зарегистрированные с помощью автозагрузчика, загружаются только при необходимости, что улучшает производительность и экономит ресурсы. ClassLoader.php управляет этим процессом.
Методы, функции и их назначение:
-
Метод
addPsr4:- Назначение: Регистрация новых путей для поиска классов в соответствии с форматом PSR-4.
- Как работает: Метод добавляет один или несколько директорий для заданного префикса пространства имен (namespace). Это позволяет системе находить соответствующие файлы классов по указанным путям. Можно добавлять пути либо в начало, либо в конец списка, в зависимости от флага.
-
Метод
set:- Назначение: Регистрация путей для PSR-0.
- Как работает: Этот метод добавляет или заменяет директории для заданного префикса, используя стандарт PSR-0. Это старый стандарт автозагрузки, который, однако, всё ещё используется в некоторых проектах и библиотеках.
-
Метод
setPsr4:- Назначение: Регистрация путей для PSR-4.
- Как работает: Метод работает аналогично методу
set, но для стандарта PSR-4. Он перезаписывает все пути для пространства имен, если они уже были зарегистрированы.
-
Метод
setUseIncludePath:- Назначение: Включение или выключение поиска классов в пути включения.
- Как работает: Этот метод позволяет указать, следует ли искать классы в стандартном пути включения PHP (например, используя
include_path).
-
Метод
getUseIncludePath:- Назначение: Проверка, активирован ли поиск классов в пути включения.
- Как работает: Возвращает флаг, указывающий, используется ли текущий путь для включения файлов классов.
-
Метод
setClassMapAuthoritative:- Назначение: Установить флаг, указывающий, что карты классов должны быть авторитетными.
- Как работает: Если флаг установлен, то система не будет пытаться искать классы в других путях, если они не указаны в карте классов.
-
Метод
getApcuPrefix:- Назначение: Возвращает префикс для кеширования с помощью APCu, если используется кеширование.
- Как работает: Метод проверяет, включен ли расширение APCu, и если оно включено, возвращает префикс, который используется для кеширования файлов классов.
-
Метод
register:- Назначение: Регистрация автозагрузчика в глобальной системе автозагрузки PHP.
- Как работает: Этот метод добавляет текущий автозагрузчик в стек автозагрузки с помощью
spl_autoload_register. Это позволяет системе автоматически загружать классы, когда они требуются.
-
Метод
unregister:- Назначение: Отмена регистрации автозагрузчика.
- Как работает: Метод удаляет автозагрузчик из стека с помощью
spl_autoload_unregister.
-
Метод
loadClass:
- Назначение: Загрузка класса.
- Как работает: Когда вызывается метод для загрузки класса, этот метод проверяет, существует ли соответствующий файл и включает его.
- Метод
findFile:
- Назначение: Поиск пути до файла класса.
- Как работает: Этот метод проверяет несколько стратегий поиска для нахождения файла класса, включая поиск по картам классов, стандартам PSR-4 и PSR-0, а также проверку через кеш APCu, если он используется.
- Метод
findFileWithExtension:
- Назначение: Поиск файла с указанным расширением.
- Как работает: Это вспомогательный метод, который помогает найти файл класса, добавляя к его пути соответствующее расширение, такое как
.phpили.hh(для HHVM).
- Метод
initializeIncludeClosure:
- Назначение: Инициализация замыкания для безопасного включения файлов.
- Как работает: Если замыкание ещё не инициализировано, оно создается, чтобы гарантировать, что файлы будут включены с ограниченным доступом к переменным и методам объекта (предотвращая использование
$thisиselfв этих файлах).
Суть содержания кода и выполняемые задачи:
Основной задачей ClassLoader.php является обеспечение эффективной и гибкой автозагрузки классов и интерфейсов, удовлетворяя стандартам PSR-0 и PSR-4. Это позволяет системе Cotonti динамически загружать необходимые файлы с классами, не тратя время на предварительное подключение каждого файла вручную. Файл также поддерживает кеширование с помощью APCu, что ускоряет процесс загрузки классов.
Ключевыми условиями, которые обрабатывает этот файл, являются:
- Управление поиском классов в разных пространствах имен.
- Работа с картами классов для ускоренного поиска.
- Использование нескольких стандартов автозагрузки (PSR-4 и PSR-0).
- Кеширование результатов для повышения производительности.
- Возможность регистрации и отмены регистрации автозагрузчика.
Таким образом, ClassLoader.php является важной частью инфраструктуры Cotonti, обеспечивая бесперебойную работу с классами и интерфейсами, что критически важно для работы всех компонентов фреймворка.
/* * This file is part of Composer. * * (c) Nils Adermann <[email protected]> * Jordi Boggiano <[email protected]> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ // Комментарии с авторскими правами и лицензией, указывающие, что этот файл является частью Composer и предоставляется согласно лицензии, находящейся в файле LICENSE. namespace Composer\Autoload; // Определение пространства имен для этого класса, указание, что этот класс принадлежит автозагрузчику Composer. class ClassLoader // Начало определения класса ClassLoader, который отвечает за автозагрузку классов по стандартам PSR-0, PSR-4 и с использованием classmap. { /** @var \Closure(string):void */ private static $includeFile; // Статическая переменная для хранения анонимной функции (Closure), которая используется для включения файлов. Этот метод может быть настроен динамически. /** @var string|null */ private $vendorDir; // Переменная экземпляра класса, которая может содержать путь к директории с установленными пакетами (vendor). Может быть пустой.
// PSR-4
/**
* @var array<string, array<string, int>>
*/
private $prefixLengthsPsr4 = array(); // Переменная для хранения длин префиксов в соответствии с PSR-4, где ключ - это префикс, а значение - массив с длинами.
/**
* @var array<string, list<string>>
*/
private $prefixDirsPsr4 = array(); // Переменная для хранения директорий для префиксов по стандарту PSR-4. Для каждого префикса будет список директорий.
/**
* @var list<string>
*/
private $fallbackDirsPsr4 = array(); // Переменная для хранения резервных директорий, которые будут использоваться в случае отсутствия класса в основных директориях PSR-4.
// PSR-0
/**
* List of PSR-0 prefixes
*
* Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
*
* @var array<string, array<string, list<string>>>
*/
private $prefixesPsr0 = array(); // Переменная для хранения префиксов по стандарту PSR-0, структурированная по первой букве префикса, с путями для каждого префикса.
/**
* @var list<string>
*/
private $fallbackDirsPsr0 = array(); // Переменная для хранения резервных директорий, которые будут использоваться в случае отсутствия класса по стандарту PSR-0.
/** @var bool */
private $useIncludePath = false; // Переменная для указания, нужно ли использовать include_path для поиска классов.
/**
* @var array<string, string>
*/
private $classMap = array(); // Переменная для хранения отображений классов в массиве, где ключ - это имя класса, а значение - путь к файлу.
/** @var bool */
private $classMapAuthoritative = false; // Переменная, указывающая, является ли класс мапа авторитетным (надежным).
/**
* @var array<string, bool>
*/
private $missingClasses = array(); // Переменная для отслеживания отсутствующих классов, где ключ - имя класса, а значение - булево значение.
/** @var string|null */
private $apcuPrefix; // Переменная для хранения префикса для использования с APCu кешем (если используется).
/**
* @var array<string, self>
*/
private static $registeredLoaders = array(); // Статическая переменная для хранения зарегистрированных загрузчиков классов, где ключ - это имя загрузчика, а значение - экземпляр класса.
/**
* @param string|null $vendorDir
*/
public function __construct($vendorDir = null) // Конструктор класса, принимающий необязательный параметр $vendorDir, который указывает директорию поставщика.
{
$this->vendorDir = $vendorDir; // Устанавливает значение параметра $vendorDir в свойство объекта $vendorDir.
self::initializeIncludeClosure(); // Вызывает статический метод для инициализации замыкания для включения файлов.
}
/**
* @return array<string, list<string>>
*/
public function getPrefixes() // Метод для получения всех префиксов PSR-0.
{
if (!empty($this->prefixesPsr0)) { // Проверяет, не пустой ли массив префиксов PSR-0.
return call_user_func_array('array_merge', array_values($this->prefixesPsr0)); // Если префиксы PSR-0 существуют, объединяет их в один массив и возвращает.
}
return array(); // Если префиксы PSR-0 пусты, возвращает пустой массив.
}
/**
* @return array<string, list<string>>
*/
public function getPrefixesPsr4() // Метод для получения всех префиксов PSR-4.
{
return $this->prefixDirsPsr4; // Возвращает массив префиксов для PSR-4, ассоциированный с директориями.
}
/**
* @return list<string>
*/
public function getFallbackDirs() // Метод для получения всех fallback директорий для PSR-0.
{
return $this->fallbackDirsPsr0; // Возвращает массив директорий fallback для PSR-0.
}
/**
* @return list<string>
*/
public function getFallbackDirsPsr4() // Метод для получения всех fallback директорий для PSR-4.
{
return $this->fallbackDirsPsr4; // Возвращает массив директорий fallback для PSR-4.
}
/**
* @return array<string, string> Array of classname => path
*/
public function getClassMap() // Метод для получения карты классов.
{
return $this->classMap; // Возвращает карту классов с ключом в виде имени класса и значением — пути к файлу.
}
/**
* @param array<string, string> $classMap Class to filename map
*
* @return void
*/
public function addClassMap(array $classMap) // Метод для добавления новой карты классов.
{
if ($this->classMap) { // Проверяет, есть ли уже существующая карта классов.
$this->classMap = array_merge($this->classMap, $classMap); // Если карта классов существует, объединяет текущую и новую карту.
} else {
$this->classMap = $classMap; // Если карты классов нет, устанавливает новую.
}
}
/**
* Регистрирует набор директорий PSR-0 для заданного префикса, либо
* добавляя в начало, либо в конец ранее заданных директорий для этого префикса.
*
* @param string $prefix Префикс
* @param list<string>|string $paths Корневые директории PSR-0
* @param bool $prepend Нужно ли добавить директории в начало
*
* @return void
*/
public function add($prefix, $paths, $prepend = false) // Метод для регистрации PSR-0 директорий для указанного префикса.
{
$paths = (array) $paths; // Преобразует $paths в массив, если это не массив, для удобства дальнейшей работы.
if (!$prefix) { // Если префикс не задан (например, глобальные директории).
if ($prepend) { // Если нужно добавить директории в начало массива.
$this->fallbackDirsPsr0 = array_merge(
$paths, // Добавляем новые директории в начало массива.
$this->fallbackDirsPsr0 // Сохраняем существующие директории после новых.
);
} else { // Если нужно добавить директории в конец массива.
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0, // Сохраняем старые директории на первом месте.
$paths // Добавляем новые директории в конец.
);
}
return; // Завершаем выполнение метода, так как префикс не был задан.
}
$first = $prefix[0]; // Берем первую букву префикса для дальнейшего поиска в массиве.
if (!isset($this->prefixesPsr0[$first][$prefix])) { // Если для данного префикса еще не существует списка директорий.
$this->prefixesPsr0[$first][$prefix] = $paths; // Регистрируем новый префикс с соответствующими директориями.
return; // Завершаем выполнение метода, так как префикс был успешно зарегистрирован.
}
if ($prepend) { // Если нужно добавить директории в начало уже существующего списка для префикса.
$this->prefixesPsr0[$first][$prefix] = array_merge(
$paths, // Добавляем новые директории в начало текущих.
$this->prefixesPsr0[$first][$prefix] // Оставляем старые директории после новых.
);
} else { // Если нужно добавить директории в конец уже существующего списка для префикса.
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix], // Сохраняем старые директории в начале.
$paths // Добавляем новые директории в конец.
);
}
}
/**
* Регистрирует набор директорий PSR-4 для заданного пространства имен, либо
* добавляя в начало, либо в конец ранее заданных директорий для этого пространства имен.
*
* @param string $prefix Префикс/пространство имен, с завершающим '\\'
* @param list<string>|string $paths Основные директории PSR-4
* @param bool $prepend Нужно ли добавить директории в начало
*
* @throws \InvalidArgumentException
*
* @return void
*/
public function addPsr4($prefix, $paths, $prepend = false) // Метод для регистрации PSR-4 директорий для указанного пространства имен.
{
$paths = (array) $paths; // Преобразует $paths в массив, если это не массив, для удобства дальнейшей работы.
if (!$prefix) { // Если префикс не задан (например, для корневого пространства имен).
// Регистрируем директории для корневого пространства имен.
if ($prepend) { // Если нужно добавить директории в начало массива.
$this->fallbackDirsPsr4 = array_merge(
$paths, // Добавляем новые директории в начало массива.
$this->fallbackDirsPsr4 // Сохраняем старые директории после новых.
);
} else { // Если нужно добавить директории в конец массива.
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4, // Сохраняем старые директории на первом месте.
$paths // Добавляем новые директории в конец.
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) { // Если для данного префикса еще не зарегистрированы директории.
// Регистрируем директории для нового пространства имен.
$length = strlen($prefix); // Определяем длину префикса для использования в дальнейшем.
if ('\\' !== $prefix[$length - 1]) { // Проверка, что префикс заканчивается на символ разделителя пространства имен.
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); // Если не заканчивается, выбрасываем исключение.
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; // Сохраняем длину префикса для дальнейшего использования.
$this->prefixDirsPsr4[$prefix] = $paths; // Регистрируем директории для данного префикса.
} elseif ($prepend) { // Если директории для данного пространства имен уже зарегистрированы и нужно добавить их в начало.
// Добавляем новые директории в начало существующего списка для префикса.
$this->prefixDirsPsr4[$prefix] = array_merge(
$paths, // Новые директории.
$this->prefixDirsPsr4[$prefix] // Старые директории.
);
} else { // Если директории для данного пространства имен уже зарегистрированы и нужно добавить их в конец.
// Добавляем новые директории в конец существующего списка для префикса.
$this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix], // Старые директории.
$paths // Новые директории.
);
}
}
/**
* Регистрирует набор директорий PSR-0 для заданного префикса,
* заменяя все ранее заданные для этого префикса.
*
* @param string $prefix Префикс
* @param list<string>|string $paths Основные директории PSR-0
*
* @return void
*/
public function set($prefix, $paths) // Метод для регистрации наборов директорий PSR-0 с заменой предыдущих.
{
if (!$prefix) { // Если префикс не задан (для корневого пространства имен).
$this->fallbackDirsPsr0 = (array) $paths; // Присваиваем новые директории для корневого пространства имен.
} else { // Если префикс задан.
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; // Присваиваем новые директории для указанного префикса.
}
}
/**
* Регистрирует набор директорий PSR-4 для заданного пространства имен,
* заменяя все ранее заданные для этого пространства имен.
*
* @param string $prefix Префикс/пространство имен, с завершающим '\\'
* @param list<string>|string $paths Основные директории PSR-4
*
* @throws \InvalidArgumentException
*
* @return void
*/
public function setPsr4($prefix, $paths) // Метод для регистрации наборов директорий PSR-4 с заменой предыдущих.
{
if (!$prefix) { // Если префикс не задан (для корневого пространства имен).
$this->fallbackDirsPsr4 = (array) $paths; // Присваиваем новые директории для корневого пространства имен.
} else { // Если префикс задан.
$length = strlen($prefix); // Определяем длину префикса.
if ('\\' !== $prefix[$length - 1]) { // Проверяем, что префикс заканчивается на разделитель пространства имен.
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); // Если не заканчивается, выбрасываем исключение.
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; // Сохраняем длину префикса.
$this->prefixDirsPsr4[$prefix] = (array) $paths; // Присваиваем новые директории для указанного префикса.
}
}
/**
* Включает поиск файлов классов в пути включения.
*
* @param bool $useIncludePath
*
* @return void
*/
public function setUseIncludePath($useIncludePath) // Метод для включения поиска в пути включения.
{
$this->useIncludePath = $useIncludePath; // Устанавливает значение флага, указывающего на использование пути включения.
}
/**
* Может быть использован для проверки, использует ли автозагрузчик путь включения для поиска классов.
*
* @return bool
*/
public function getUseIncludePath() // Метод для получения текущего значения флага использования пути включения.
{
return $this->useIncludePath; // Возвращает текущее состояние флага.
}
/**
* Отключает поиск классов в префиксах и запасных директориях, которые не были зарегистрированы в карте классов.
*
* @param bool $classMapAuthoritative
*
* @return void
*/
public function setClassMapAuthoritative($classMapAuthoritative) // Метод для включения/выключения использования карты классов.
{
$this->classMapAuthoritative = $classMapAuthoritative; // Устанавливает значение флага, указывающего на авторитетность карты классов.
}
/**
* Должен ли поиск класса завершаться ошибкой, если класс не найден в текущей карте классов?
*
* @return bool
*/
public function isClassMapAuthoritative() // Метод для проверки, является ли карта классов авторитетной.
{
return $this->classMapAuthoritative; // Возвращает текущий статус флага авторитетности карты классов.
}
/**
* Префикс APCu для кэширования найденных/не найденных классов, если расширение включено.
*
* @param string|null $apcuPrefix
*
* @return void
*/
public function setApcuPrefix($apcuPrefix) // Метод для установки префикса APCu для кэширования.
{
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; // Устанавливает префикс APCu, если расширение APCu включено, иначе null.
}
/**
* Префикс APCu в использовании, или null, если кэширование APCu не включено.
*
* @return string|null
*/
public function getApcuPrefix() // Метод для получения текущего префикса APCu.
{
return $this->apcuPrefix; // Возвращает префикс APCu или null, если кэширование не включено.
}
/**
* Регистрирует этот экземпляр как автозагрузчик.
*
* @param bool $prepend Нужно ли добавлять автозагрузчик в начало списка
*
* @return void
*/
public function register($prepend = false) // Метод для регистрации автозагрузчика.
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend); // Регистрирует метод loadClass как автозагрузчик с приоритетом в зависимости от $prepend.
if (null === $this->vendorDir) { // Проверка, если директория vendor не задана.
return; // Если директория не задана, метод завершается.
}
if ($prepend) { // Если необходимо добавить в начало списка зарегистрированных автозагрузчиков.
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders; // Добавляет текущий автозагрузчик в начало списка.
} else { // Если автозагрузчик добавляется в конец списка.
unset(self::$registeredLoaders[$this->vendorDir]); // Удаляет текущий автозагрузчик из списка (если он уже был).
self::$registeredLoaders[$this->vendorDir] = $this; // Добавляет текущий автозагрузчик в конец списка.
}
}
/**
* Отменяет регистрацию этого экземпляра как автозагрузчика.
*
* @return void
*/
public function unregister() // Метод для отмены регистрации автозагрузчика.
{
spl_autoload_unregister(array($this, 'loadClass')); // Отменяет регистрацию метода loadClass как автозагрузчика.
if (null !== $this->vendorDir) { // Проверка, если директория vendor задана.
unset(self::$registeredLoaders[$this->vendorDir]); // Удаляет текущий автозагрузчик из списка зарегистрированных.
}
}
/**
* Загружает указанный класс или интерфейс.
*
* @param string $class Имя класса
* @return true|null Возвращает true, если класс был загружен, иначе null
*/
public function loadClass($class) // Метод для загрузки класса.
{
if ($file = $this->findFile($class)) { // Если файл, соответствующий классу, найден.
$includeFile = self::$includeFile; // Получение функции для включения файла.
$includeFile($file); // Включение файла, который содержит класс.
return true; // Возвращает true, если файл был успешно загружен.
}
return null; // Возвращает null, если файл не был найден.
}
/**
* Находит путь к файлу, в котором определён класс.
*
* @param string $class Имя класса
*
* @return string|false Путь к файлу, если найден, иначе false
*/
public function findFile($class) // Метод для поиска пути к файлу, содержащему класс.
{
// Поиск в карте классов
if (isset($this->classMap[$class])) { // Если класс найден в классовой карте.
return $this->classMap[$class]; // Возвращает путь к файлу из карты классов.
}
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { // Если карта классов авторитетная или класс уже был определён как отсутствующий.
return false; // Возвращает false, если класс не найден.
}
if (null !== $this->apcuPrefix) { // Если задан префикс для кэширования APCu.
$file = apcu_fetch($this->apcuPrefix.$class, $hit); // Ищет путь к файлу в кэше APCu.
if ($hit) { // Если файл найден в кэше.
return $file; // Возвращает путь к файлу из кэша.
}
}
$file = $this->findFileWithExtension($class, '.php'); // Ищет файл с расширением .php.
// Ищет файлы Hack, если используется HHVM
if (false === $file && defined('HHVM_VERSION')) { // Если файл с расширением .php не найден и запущен HHVM.
$file = $this->findFileWithExtension($class, '.hh'); // Ищет файл с расширением .hh.
}
if (null !== $this->apcuPrefix) { // Если задан префикс для кэширования APCu.
apcu_add($this->apcuPrefix.$class, $file); // Добавляет путь к файлу в кэш APCu.
}
if (false === $file) { // Если файл не найден.
// Запоминает, что этот класс не существует.
$this->missingClasses[$class] = true; // Отмечает класс как отсутствующий.
}
return $file; // Возвращает путь к файлу, если найден, иначе false.
}
/**
* Возвращает текущие зарегистрированные загрузчики, индексированные по их соответствующим каталогам поставщиков.
*
* @return array<string, self> Массив зарегистрированных загрузчиков с ключами — директории поставщиков.
*/
public static function getRegisteredLoaders() // Статический метод для получения списка всех зарегистрированных загрузчиков.
{
return self::$registeredLoaders; // Возвращает массив зарегистрированных загрузчиков.
}
/**
* Находит путь к файлу, где определён класс, с учётом расширения.
*
* @param string $class Имя класса
* @param string $ext Расширение файла, например, '.php'
* @return string|false Путь к файлу, если найден, или false в противном случае
*/
private function findFileWithExtension($class, $ext) // Приватный метод для поиска файла класса по расширению
{
// Поиск по PSR-4
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; // Преобразование пространства имён в путь для PSR-4
$first = $class[0]; // Первая буква префикса
if (isset($this->prefixLengthsPsr4[$first])) { // Если префиксы для PSR-4 существуют для данной буквы
$subPath = $class; // Начальный путь — имя класса
while (false !== $lastPos = strrpos($subPath, '\\')) { // Пытаемся найти последний символ '\\'
$subPath = substr($subPath, 0, $lastPos); // Обрезаем путь до последнего разделителя
$search = $subPath . '\\'; // Формируем путь для поиска
if (isset($this->prefixDirsPsr4[$search])) { // Если такой префикс найден в директориях PSR-4
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); // Окончание пути
foreach ($this->prefixDirsPsr4[$search] as $dir) { // Перебираем все директории
if (file_exists($file = $dir . $pathEnd)) { // Если файл существует
return $file; // Возвращаем путь к файлу
}
}
}
}
}
// Поиск в fallback-диках для PSR-4
foreach ($this->fallbackDirsPsr4 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { // Если файл существует в fallback-диках
return $file;
}
}
// Поиск по PSR-0
if (false !== $pos = strrpos($class, '\\')) { // Если класс имеет пространство имён
// Путь для PSR-0 с учётом пространства имён
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
} else { // Если класс без пространства имён (например, PEAR-like)
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; // Преобразуем название класса в путь для PSR-0
}
if (isset($this->prefixesPsr0[$first])) { // Если префиксы для PSR-0 существуют для данной буквы
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { // Перебираем все префиксы
if (0 === strpos($class, $prefix)) { // Если класс начинается с данного префикса
foreach ($dirs as $dir) { // Перебираем все директории для этого префикса
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { // Если файл существует
return $file;
}
}
}
}
}
// Поиск в fallback-диках для PSR-0
foreach ($this->fallbackDirsPsr0 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { // Если файл существует в fallback-диках
return $file;
}
}
// Поиск в путях для включений, если используется include_path.
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { // Если используется include_path
return $file;
}
return false; // Если файл не найден, возвращаем false
}
/**
* Инициализирует замыкание для включения файлов, если оно ещё не инициализировано.
*
* @return void
*/
private static function initializeIncludeClosure()
{
if (self::$includeFile !== null) { // Если замыкание уже инициализировано, выходим из метода
return;
}
/**
* Изолированное включение.
*
* Предотвращает доступ к $this/self из включённых файлов.
*
* @param string $file Путь к файлу для включения
* @return void
*/
self::$includeFile = \Closure::bind(static function($file) { // Создаём замыкание для включения файла
include $file; // Включаем файл
}, null, null); // Замыкание не привязывается к конкретному объекту или классу
}
}
Комментарии (0)
Автор контента
Оффлайн
Sodium Carbonate
Последняя авторизация: 20.07.2026 00:04
- Страница размещена: 30.01.2025 17:56
- Последнее обновление: 30.01.2025 22:50