Допустим, я выпустил библиотеку кода как отдельный класс PHP. Затем кто-то использует версию 1.0 этой библиотеки в своем приложении. Позже я выпускаю версию 2.0 библиотеки, и тот же самый человек, по любой причине, должен использовать в своих приложениях одновременно 1.0 и 2.0, потому что он или я нарушили обратную совместимость с новым выпуском.
Если имена классов отличаются, достаточно легко включить и создать оба экземпляра, потому что нет конфликта имен. Но если имена классов остаются неизменными, мы сталкиваемся с проблемами:
include /lib/api-1.0/library.php;
$oldlibary = new Library();
include /lib/api-2.0/library.php;
$newlibrary = new Library();
Это просто не сработает, потому что мы не можем загрузить два класса с именем Library
. Другой вариант, предложенный другим разработчиком, заключался в использовании пространств имен. Следующие должны работать:
namespace old {
include /lib/api-1.0/library.php;
}
namespace new {
include /lib/api-2.0/library.php;
}
$oldlibary = new old\Library();
$newlibrary = new new\Library();
К сожалению, это не очень масштабируемо. Это будет работать с ситуацией с двумя экземплярами (которую, я надеюсь, мне не пришлось бы использовать в первую очередь), но чтобы масштабировать ее до 3, 4, 5 или более экземпляров, вам необходимо определить дополнительные пространства имен и настройте, если вы не используете эти пространства имен, это куча ненужного кода.
Так есть ли способ динамически создать пространство имен, включить файл и создать экземпляр класса, содержащегося в этом файле, в переменной с уникальным именем?
Позвольте мне добавить еще несколько уточнений ...
Я создаю набор библиотек, которые будут использоваться другими разработчиками, которые создают плагины / модули для пары платформ CMS. В идеале каждый должен всегда использовать последнюю версию моей библиотеки, но я не могу этого гарантировать, и я не могу гарантировать, что конечный пользователь всегда будет обновлять свои модули при появлении новых версий.
Вариант использования, с которым я пытаюсь работать, - это случай, когда конечный пользователь устанавливает два разных модуля двумя разными разработчиками: назовите их Apple и Orange . Оба модуля используют версию 1.0 моей библиотеки, и это здорово. Мы можем создать его экземпляр один раз , и оба набора кода могут воспользоваться его функциональностью.
Позже я выпускаю небольшой патч для этой библиотеки. Это версия 1.1, потому что она не нарушает обратную совместимость с веткой 1.x. Разработчик Apple немедленно обновляет свою локальную версию и выпускает новую версию своей системы. Разработчик Orange в отпуске и не беспокоится.
Когда конечный пользователь обновляет Apple , она получает последнюю версию технической поддержки моей библиотеки. Поскольку это вспомогательный выпуск, предполагается, что он полностью заменяет версию 1.0. Таким образом, код создает только экземпляры 1.1, а Orange получает выгоду от исправления, даже если разработчик не удосужился обновить их выпуск.
Даже позже я решил обновить свой API, чтобы по какой-то причине добавить некоторые хуки в Facebook. Новые функции и расширения API сильно меняются в библиотеке, поэтому я поднял версию до 2.0, чтобы пометить ее как потенциально несовместимую во всех ситуациях. Еще раз, Apple входит и обновляет свой код. Ничего не сломалось, он просто заменил мою библиотеку в папке /lib
на последнюю версию. Оранжевый решил вернуться в школу, чтобы стать клоуном, и, тем не менее, прекратил поддерживать свой модуль, поэтому он не получает никаких обновлений.
Когда конечный пользователь обновляет Apple с новым выпуском, она автоматически получает версию 2.0 моей библиотеки. Но Orange имел в своей системе код, который уже добавил хуки для Facebook, поэтому возникнет конфликт, если 2.0 по умолчанию будет добавлен в его библиотеку. Поэтому вместо полной замены я создаю экземпляр 2.0 один раз для Apple и, параллельно, создаю экземпляр версии 1.0, поставляемой с Orange , чтобы он мог использовать правильный код.
Весь смысл этого проекта - позволить сторонним разработчикам создавать системы на основе моего кода, не полагаясь на их надежность, и обновлять свой код, когда они должны.Ничто не должно нарушать работу конечного пользователя, и обновление моей библиотеки, когда она используется внутри чужой системы, должно быть простой заменой файла, не проходя и не изменяя все ссылки на классы.