Вопрос

Я хотел бы осмыслить использование атрибутов расширения, например, для элементов цитат.
Нет проблем добавить пользовательский атрибут к такой сущности с помощью класса настройки, как в Magento 1, этот вопрос не об этом.
В настоящий момент меня охватывает волшебство, когда я хочу представить такой атрибут, который был добавлен расширением через API сущностей, в качестве атрибута расширения.

ОБНОВЛЯТЬ: Я знаю, как генерируются обычные фабрики.Этот вопрос касается специальных фабрик, которые создают экземпляры сгенерированных реализаций для сгенерированных интерфейсов атрибутов расширения.

Вот шаги, которые я предпринимаю, чтобы заставить его работать.Я добавляю их, чтобы тому, кто попытается ответить, не нужно было вдаваться в эти детали.
Мой вопрос КАК или ПОЧЕМУ оно работает.

Шаги по предоставлению атрибута расширения через API сущности:

  1. Создать etc/extension_attributes.xml который добавляет атрибут в интерфейс объекта
  2. Создайте плагин для добавления значения атрибута к объектам. 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 а его нет, происходит следующее:

  1. Автозагрузчику не удается создать экземпляр класса и здесь инициирует генерацию кода. \Magento\Framework\Code\Generator\Autoloader::load
  2. Тогда суффикс класса определяется как Factory (список всех заявленных суффиксов можно найти здесь \Magento\Framework\ObjectManager\DefinitionFactory::getCodeGenerator) и соответствующий класс генератора Factory (Magento\Framework\ObjectManager\Code\Generator\Factory) используется для создания отсутствующей фабрики
  3. Все автоматически сгенерированные классы всегда основаны на других классах, в случае фабрики имя исходного класса вычисляется просто путем удаления Factory суффикс, это будет Magento\Quote\Api\Data\CartItemExtension.Этот класс не существует, и автогенерация снова вызывается автозагрузчиком, но на этот раз для класса расширения.
  4. Теперь суффикс Extension и \Magento\Framework\Api\Code\Generator\ExtensionAttributesGenerator будет использоваться для создания этого класса
  5. Исходный класс для генерации класса расширения рассчитывается как Magento\Quote\Api\Data\CartItemInterface, он существует и класс расширения успешно создан.Однако при попытке включить файл класса расширения автогенерация запускается еще раз, поскольку Magento\Quote\Api\Data\CartItemExtension реализует Magento\Quote\Api\Data\CartItemExtensionInterface, которого не существует
  6. Суффикс ExtensionInterface и \Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceGenerator будет использоваться для генерации
  7. Классы ExtensionInterface и Extension генерируются на основе информации из extension_attributes.xml, доступный через \Magento\Framework\Api\ExtensionAttribute\Config, затем генерируется Factory

Важно отметить, что ExtensionInterface не имеет предпочтений в di.xml потому что и Extension, и ExtensionInterface генерируются автоматически.Это не проблема, поскольку не предполагается, что ExtentionInterface будет внедрен напрямую через конструкцию.

Другие советы

Сегодня вечером поверх ответа @Alex я вижу строки

$modelReflection = new \ReflectionClass($extensibleClassName);
        if ($modelReflection->isInterface()
            && $modelReflection->isSubclassOf(self::EXTENSIBLE_INTERFACE_NAME)
            && $modelReflection->hasMethod('getExtensionAttributes')
        ) {
            $this->classInterfaceMap[$extensibleClassName] = $extensibleClassName;
            return $this->classInterfaceMap[$extensibleClassName];
        }

в классе \Magento\Framework\Api\ExtensionAttributesFactory

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

эти строки говорят:

  • это класс в нашем Extension_attributes интерфейс

  • расширяет ли он \Magento\Framework\Api\ExtensibleDataInterface

  • имеет этот интерфейс функцию getExtensionAttributes

Лицензировано под: CC-BY-SA с атрибуция
Не связан с magento.stackexchange
scroll top