Порядок выполнения нескольких Автозагрузчиков Composer


У меня есть проект с несколькими модулями. Каждый модуль использует Composer внутри себя и в основном независим от других модулей.

Однако некоторые модули имеют общие зависимости, которые имеют разные версии. Эти зависимости по большей части обратно совместимы и используют семантическое управление версиями.

Я хотел бы убедиться, что зависимость с самой высокой семантической версией имеет приоритет. Это позволит всем модулям совместно использовать одну и ту же зависимость и обратно совместимость этих зависимостей гарантирует, что ничто не нарушится.

Мой план состоял в том, чтобы сделать это, контролируя порядок, в котором я вызываю require_once на отдельных автопогрузчиках. Ниже приведен пример кода, который на практике генерируется.
require_once(__DIR__ . '/moduleA/vendor/autoload.php');
require_once(__DIR__ . '/moduleB/vendor/autoload.php');
require_once(__DIR__ . '/moduleC/vendor/autoload.php');
Основное предположение, которое я сделал, состояло в том, что если автопогрузчик требуется перед другим, он будет иметь приоритет над более поздними. Однако я обнаружил, что противоположностьистинна. Автопогрузчик, который приходит последнее , кажется, имеет преимущество над остальными.

Рассмотрим класс FooMyClass, который является зависимостью, разделяемой между этими модулями. Я ожидаю, что с указанным выше порядком загрузки FooMyClass будет поднят из moduleA/vendor/....

Вместо этого приходит форма moduleC/vendor/....

Я мог бы перевернуть свой сгенерированный заказ, чтобы обойти это, но я хотел бы проверить, существует ли предсказуемый порядок, в котором загружаются PHP.

Существует ли порядок, в котором PHP выполняет Автозаполнители? Сделать несколько На это как-то влияют автопогрузчики композитора?

Спасибо.

1 7

1 ответ:

На самом деле, вы находитесь в беспорядке, но вы уже на полпути из этого беспорядка, не видя.

Что плохо в вашей ситуации, так это то, что ваши модули потенциально могут зависеть от несовместимых сторонних библиотек. Вы упоминаете, что они используют семантическое управление версиями, но это только покрывает совместимость вверх, например "незначительная версия увеличивается, если новая функция добавляется совместимым образом к старой версии". Это означает, что эта новая версия не является обратно совместимой!

Предположим, модуль A использует версию 1.0.7 библиотеки, а модуль B использует версию 1.2.5. Эта библиотека получила новый метод, добавленный в класс в версии 1.2, и модуль B использует этот метод. Может ли модуль B работать с классом версии 1.0.7 модуля A? Конечно, нет. Вы хотите, чтобы оба модуля работали с самой высокой совместимой версией для обоих модулей, 1.2.5.

Как это сделать? Используйте только один автозагрузчик Composer и только одно определение центральной зависимости.

Если бы вы могли создать файл composer.json, который содержит зависимости для всех модулей A, B и C, и каждый модуль заявляет о своих зависимостях от других библиотек, Composer соберет все эти библиотеки, вычислит из них" лучшую " полезную версию и создаст загрузчик, который однозначно загрузит только эти библиотеки.

Дополнительное преимущество: только одна версия на библиотеку без дубликатов. Только один объект autoloader с глобальными знаниями обо всех доступных классах (что может немного оптимизировать загрузку).

А ты мы уже на полпути туда. Каждый из ваших модулей должен уже иметь локальный composer.json, который определяет требования к версии. Добавьте определение для автоматической загрузки самого модуля и дайте ему имя. Затем вы можете ссылаться на это имя в Центральном composer.json (вероятно, вам нужно будет добавить репозитории, если они являются частными), и вы почти закончили. Возможно, есть некоторая возня с путями, Если вам действительно нужны эти модули в определенном пути.

Но это все.

И затем вы решаете одну другую вопрос: Что делать, если модулю а нужна небольшая часть модуля Б? С помощью Composer вы можете указать эту зависимость вместе со всеми библиотеками, и даже если вы забудете установить модуль B, Composer сделает это за вас или напомнит вам об этом.