Я хотел бы обернуть голову, используя атрибуты расширения, например, для элементов цитаты.
Нет проблем с добавлением пользовательского атрибута к такой сущности с помощью класса установки, как в Magento 1, это не то, о чем этот вопрос.
В тот момент магия поражает меня, когда я хочу выставить такой атрибут, который был добавлен расширением через API сущностей в качестве атрибута расширения.
ОБНОВЛЕНИЕ : я знаю, как создаются обычные фабрики. Этот вопрос касается специальных фабрик, которые создают экземпляры сгенерированных реализаций для созданных интерфейсов атрибутов расширения.
Вот шаги, которые я предпринимаю, чтобы заставить его работать. Я добавляю их, чтобы те, кто пытается ответить, не должны вдаваться в подробности.
Мой вопрос, КАК или ПОЧЕМУ это работает.
Шаги для предоставления атрибута расширения через API объекта:
- Создайте объект,
etc/extension_attributes.xml
который добавляет атрибут в интерфейс объекта. - Создайте плагин для добавления значения атрибута к
ExtensionAttributes
экземпляру лица .
Для выполнения второго пункта ExtensionAttributes
необходим экземпляр сущностей . По этой причине плагин зависит от фабрики, которую менеджер объектов поставляет через DI.
Для примера цитаты Magento\Quote\Api\Data\CartItemExtensionFactory
должен использоваться пример .
Я думаю, что тип этой фабрики как-то должен быть триггером для магии поколения.
Затем Magento генерирует соответствующий интерфейс \Magento\Quote\Api\Data\CartItemExtensionInterface
с установщиками и получателями для всех атрибутов расширения.
Тем не менее, кажется, не генерировать конкретную реализацию для этого интерфейса. В аренду PHPStorm этого не видит.
Как Magento собирает информацию, необходимую для создания класса? Как сгенерированные методы интерфейса могут быть вызваны на конкретном экземпляре? Это класс, который генерируется только в памяти?
Я счастлив, что это работает, но это не очень приятно. Возможность Magentos использовать атрибуты, созданные автоматически расширениями, является одним из ключевых факторов его успеха. Как разработчик модулей, я считаю, что мне нужно глубокое понимание всего процесса.
Если бы у меня было время, я бы сам покопался в этом, но я бы предпочел, если бы я мог получить объяснение.
ОБНОВЛЕНИЕ 2 : Потребовалось немного времени, чтобы прочитать \Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceGenerator
и \Magento\Framework\Api\Code\Generator\ExtensionAttributesGenerator
. Теперь, по крайней мере, у меня есть приблизительное представление о том, что происходит. Если никто не побьет меня, я напишу описание всего процесса в один момент, так как я думаю, что это будет полезной ссылкой.
Ответы:
Прежде всего автогенерация происходит на основе суффикса имени класса, например
Factory
,ExtensionInterface
(см.\Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceGenerator::EXTENSION_INTERFACE_SUFFIX
) ИлиExtension
(см.\Magento\Framework\Api\Code\Generator\ExtensionAttributesGenerator::EXTENSION_SUFFIX
).Правильный генератор выбирается на основе суффикса здесь
\Magento\Framework\Code\Generator::generateClass
.Давайте предположим, что режим Magento активирован,
developer
а недостающие классы могут быть сгенерированы на лету (аналогичный процесс будет происходить при использовании компилятора). Когда менеджер объектов пытается создать экземпляр, скажем,Magento\Quote\Api\Data\CartItemExtensionFactory
и он не существует, происходит следующее:\Magento\Framework\Code\Generator\Autoloader::load
Factory
(список всех объявленных суффиксов можно найти здесь\Magento\Framework\ObjectManager\DefinitionFactory::getCodeGenerator
) и соответствующий класс генератора Factory (Magento\Framework\ObjectManager\Code\Generator\Factory
) используется для генерации отсутствующей фабрикиFactory
суффикса, так и будетMagento\Quote\Api\Data\CartItemExtension
. Этот класс не существует и автогенерация снова запускается автозагрузчиком, но на этот раз для класса ExtensionExtension
и\Magento\Framework\Api\Code\Generator\ExtensionAttributesGenerator
будет использоваться для генерации этого классаMagento\Quote\Api\Data\CartItemInterface
, как он существует, и класс расширения успешно генерируется. Тем не менее, при попытке включить файл класса расширений автогенерация запускается еще раз, потому чтоMagento\Quote\Api\Data\CartItemExtension
реализуетMagento\Quote\Api\Data\CartItemExtensionInterface
, который не существуетExtensionInterface
и\Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceGenerator
будет использоваться для генерацииextension_attributes.xml
, доступной через\Magento\Framework\Api\ExtensionAttribute\Config
, затем генерируется Factory.Важным примечанием является то, что в ExtensionInterface нет предпочтений,
di.xml
так как Extension и ExtensionInterface генерируются автоматически. Это не проблема, потому что ExtentionInterface не предполагается вводить напрямую через конструкцию.источник
Для меня сегодня вечером, в верхней части ответа от @Alex, я вижу строки
в классе
\Magento\Framework\Api\ExtensionAttributesFactory
мы можем начать отладку, если интерфейс расширения не генерируется. В значительной степени атрибуты расширения предназначены для структурирования нашего класса, как и ожидал Magento 2.
эти строки говорят:
это класс в нашем extension_attributes интерфейс
это расширяет \ Magento \ Framework \ Api \ ExtensibleDataInterface
имеет этот интерфейс функцию с именем getExtensionAttributes
источник