Composer - это менеджер зависимостей на уровне приложения для PHP. Под зависимостью понимаются библиотеки/пакеты, от которых зависит ваше приложение. Помимо управления зависимостями, composer также осуществляет автозагрузку файлов, необходимых для работы приложения. Большинство фреймворков (Laravel, Symfony и т.д.) используют composer, и он автозагружается по умолчанию.
Что такое автозагрузка?
Автозагрузка означает автоматическую загрузку файлов, необходимых для работы проекта/приложения. То есть включение файлов, необходимых для работы приложения, без явного включения их с помощью функций include() или require().
Зачем это нужно?
Включение файлов с помощью include() или require() будет правильным, если ваш проект содержит небольшое количество файлов. Но большинство реальных приложений содержат огромное количество файлов. Поэтому включение файлов с помощью вышеупомянутых функций превращается в утомительную задачу. Еще более сложной она станет, если наш проект зависит от большого количества внешних библиотек/пакетов.
Как это работает?
Давайте рассмотрим простую автозагрузку.
class Autoloader
{
public function autoLoad($className)
{
//logic for finding class path
include $fullyResolvedPath;
}
}
spl_autoload_register(['Autoloader', 'autoLoad']);
$obj = new DemoClass;
Здесь мы использовали встроенную php-функцию spl_autoload_register() для регистрации нашей функции автозагрузки. Это означает, что она говорит php
"Если ты не можешь найти класс сам, позволь мне найти его для тебя. Если я не могу найти его, то выкинь ошибку".
Внутри созданного нами автозагрузчика мы можем найти путь к классу и затем включить его с помощью функции include().
Типы автозагрузки
Composer поддерживает следующие типы автозагрузки.
- Classmap
- PSR-0
- PSR-4
- Файлы
Типы автозагрузки и ее правило могут быть определены в файле composer.json. В одном приложении можно настроить несколько типов автозагрузки. Среди них PSR-4 и PSR-0 - стандарты автозагрузки, предложенные группой PHP-FIG.
Classmap
Classmap, как следует из названия, создает отображение всех классов внутри указанных каталогов в единый массив ключ => значение, который находится в генерируемом файле vendor/composer/autoload_classmap.php. Автоматическая генерация файла происходит при установке/обновлении composer.
{
"autoload": {
"classmap": ["src/", "lib/", "Something.php"]
}
}
Сопоставление выполняется путем поиска всех классов в файлах .php и .inc в указанных каталогах. Это самый быстрый способ автозагрузки, поскольку для поиска классов используется поиск по массиву.
PSR-0
Это стандарт PSR для автозагрузки файлов до появления PSR-4, который в настоящее время является устаревшим. Вы можете определить правила PSR-0 в конфигурационном файле как отображение пространства имен на пути, относительно корня пакета/приложения.
{
"autoload": {
"psr-0": {
"Acme\\Foo\\": "src/",
"Vendor\\Namespace\\": "src/",
"Vendor_Namespace_": "src/"
}
}
}
Все ссылки на PSR-0 объединяются в один массив key => value, который находится в сгенерированном файлеvendor/composer/autoload_namespaces.php. При автозагрузке PSR-0 ищет пространство имен в сформированном массиве и разрешает путь из его значения.
Например, Acme\Foo\Bar будет преобразован в src/Acme/Foo/Bar.php. PSR-0 также поддерживает символы подчеркивания (_) в именах классов. Каждый символ _ в имени класса преобразуется в DIRECTORY_SEPARATOR. Таким образом, Acme_Foo_Bar также будет преобразован в src/Acme/Foo/Bar.php.
PSR-4
В настоящее время PSR-4 является рекомендуемым способом автозагрузки, так как он обеспечивает большую простоту использования.
{
"autoload": {
"psr-4": {
"Acme\\Foo\\": "src/",
"Vendor\\Namespace\\": ""
}
}
}
В отличие от PSR-0 подчеркивания не преобразуются в DIRECTORY_SEPARATOR, а префикс пространства имен не присутствует в пути.
Например, Acme\Foo\Bar преобразуется в src/Bar.php.
Все ссылки PSR-4 при установке/обновлении объединяются в один массив ключ => значение, который находится по адресу vendor/composer/autoload_psr4.php.
Файлы
Classmap, PSR-0 и PSR-4 работают только с классами. Если требуется автозагрузка функций, можно использовать автозагрузку файлов. Это может быть полезно для загрузки вспомогательных функций. Эти файлы будут загружаться при каждом запросе.
{
"autoload": {
"files": ["src/helpers.php"]
}
}
Замечание по Classmap и PSR-4
Автозагрузка Classmap является самой быстрой среди автозагрузчиков, поскольку она загружает классы из заранее сформированного массива. Но проблема с classmap заключается в том, что массив classmap необходимо регенерировать каждый раз, когда вы создаете новый файл класса. Поэтому в среде разработки наиболее подходящей будет автозагрузка PSR-4.
Автозагрузка PSR-4 будет медленнее, чем classmap, поскольку ей необходимо проверить файловую систему, прежде чем окончательно разрешить имя класса. Но в production мы хотим, чтобы все работало как можно быстрее.
По этой причине composer предлагает генерацию classmap из PSR-4. Генерация classmap преобразует все правила PSR-4/PSR-0 в правила classmap. Таким образом, автозагрузка будет происходить быстрее. Если класс PSR-4 не найден в сгенерированном classmap, автозагрузка возвращается к правилам PSR-0.
Генерация Classmap может быть включена одним из следующих способов.
Установить значение "optimize-autoloader": true
внутри ключа config в composer.json
Вызовите установку или обновление с параметром -o / --optimize-autoloader
Вызвать dump-autoload
с командой -o / --optimize
Собираем все вместе
Теперь мы можем рассмотреть, как composer автозагружает наши файлы, комбинируя все эти автозагрузчики. Прежде всего, нам необходимо включить файл composer autoload.php.
require __DIR__.'/../vendor/autoload.php';
Он требует наличия другого файла composer/autoload_real.php
и вызывает метод getLoader()
у сгенерированного класса автозагрузчика composer.
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitcac18dc222d8ea1e03bdef8b44290883::getLoader();
В методе getLoader()
composer загружает все массивы автозагрузки, сгенерированные при установке/обновлении composer или при выполнении composer dump-autoload
, а также регистрирует функцию автозагрузки с помощью функции spl_autoload_register()
, о которой говорилось ранее.
// autoload_real.php
public static function getLoader()
{
// ...
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
// Loads all autoloader arrays
$loader->register(true);
// ...
return $loader;
}
Метод register()
в классе ClassLoader регистрирует функцию автозагрузки loadClass()
.
class ClassLoader
{
public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
}
}
Метод loadClass()
прост. Он вызывает другой метод findFile()
с именем класса, и если метод возвращает корректный путь к файлу, то он классифицирует другую вспомогательную функцию includeFile()
с путем к файлу, которая просто включает файл по заданному пути к файлу.
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
includeFile($file);
return true;
}
}
Метод findFile() отвечает за поиск пути к файлу. Поскольку его реализация несколько сложна, мы не будем рассматривать ее здесь. Но все, что вам нужно знать, это то, что он проверяет поиск пути к файлу следующим образом.
- Проверяется, содержит ли classmap указанный класс, если находит, то сразу возвращает путь к файлу.
- Если файл не найден в classmap, то производится поиск в psr-4, если найден, то возвращается сгенерированный путь к файлу.
- Если поиск psr-4 не удался, выполняется поиск psr-0, если найден - возвращается сгенерированный путь к файлу.
Вот и все. Composer отлично справляется с автозагрузкой файлов и предоставляет множество возможностей для их настройки и облегчения разработки.