atom1c.ru
Связаться со мной

Как Composer осуществляет автозагрузку PHP-файлов

Composer - это менеджер зависимостей на уровне приложения для PHP. Под зависимостью понимаются библиотеки/пакеты, от которых зависит ваше приложение. Помимо управления зависимостями, composer также осуществляет автозагрузку файлов, необходимых для работы приложения. Большинство фреймворков (Laravel, Symfony и т.д.) используют composer, и он автозагружается по умолчанию.

Что такое автозагрузка?

Автозагрузка означает автоматическую загрузку файлов, необходимых для работы проекта/приложения. То есть включение файлов, необходимых для работы приложения, без явного включения их с помощью функций include() или require().

Автозагрузка позволяет использовать файлы PHP без необходимости require() или include() и считается отличительной чертой современного программирования.

Зачем это нужно?

Включение файлов с помощью 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 поддерживает следующие типы автозагрузки.

  1. Classmap
  2. PSR-0
  3. PSR-4
  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() отвечает за поиск пути к файлу. Поскольку его реализация несколько сложна, мы не будем рассматривать ее здесь. Но все, что вам нужно знать, это то, что он проверяет поиск пути к файлу следующим образом.

  1. Проверяется, содержит ли classmap указанный класс, если находит, то сразу возвращает путь к файлу.
  2. Если файл не найден в classmap, то производится поиск в psr-4, если найден, то возвращается сгенерированный путь к файлу.
  3. Если поиск psr-4 не удался, выполняется поиск psr-0, если найден - возвращается сгенерированный путь к файлу.

Вот и все. Composer отлично справляется с автозагрузкой файлов и предоставляет множество возможностей для их настройки и облегчения разработки.