Magento 2. Добавление расширенных атрибутов в сущность

Сторонние разработчики не могут менять API Data интерфейс Magento Core, но есть одним способ конфигурации интерфейсов, — добавление расширенных атрибутов .

Мы продемонстрируем это на примере сущности Product , Product Repository и Web Api.

Чтобы получить продукт или список продуктов через Magento API, вам нужно сделать запрос API к соответствующему сервиса (в нашем случае — Product Repository). В ответе мы получим объект со следующей структурой:

Product response:

<product>
    <id>1</id>
    <sku>some-sku</sku>
    <custom_attributes><!-- Custom Attributes Data --></custom_attributes>
    <extension_attributes><!-- Here should we add extension attributes data --></extension_attributes>
</product>

Product list response:

<products>
    <item>
        <id>1</id>
        <sku>some-sku</sku>
        <custom_attributes><!-- Custom Attributes Data --></custom_attributes>
        <extension_attributes><!-- Here should we add extension attributes data --></extension_attributes>
    </item>
    <item>
        <id>2</id>
        <sku>some-sku-2</sku>
        <custom_attributes><!-- Custom Attributes Data --></custom_attributes>
        <extension_attributes><!-- Here should we add extension attributes data --></extension_attributes>
    </item>
</products>

Добавить плагин в репозиторий продукта:

Чтобы добавить атрибуты, мы должны использовать after-плагин к Product Repository. Плагин должен слушать следующие методы: save, get, getList.

Мы можем добавлять скалярные и нескалярные атрибуты расширения.

Скалярный — простой атрибут. Нескалярный атрибут может быть представлять Data Object.

    <?php
       public function afterGet
        (
            \Magento\Catalog\Api\ProductRepositoryInterface $subject,
            \Magento\Catalog\Api\Data\ProductInterface $entity
        ) {
            $ourCustomData = $this->customDataRepository->get($entity->getId());

            $extensionAttributes = $entity->getExtensionAttributes(); /** get current extension attributes from entity **/
            $extensionAttributes->setOurCustomData($ourCusomData);
            $entity->setExtensionAttributes($extensionAttributes);

            return $entity;
        }

    ?>

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

AfterGetList похож на afterGet.

Аналогичным образом плагин AfterSave должен принимать данные от сущности и выполнять некоторые манипуляции:

    <?php
           public function afterSave
            (
                \Magento\Catalog\Api\ProductRepositoryInterface $subject,
                \Magento\Catalog\Api\Data\ProductInterface $entity
            ) {
                $extensionAttributes = $entity->getExtensionAttributes(); /** get current extension attributes from entity **/
                $ourCustomData = $extensionAttributes->getOurCustomData();
                $this-customDataRepository->save($ourCustomData);

                return $entity;
            }

        ?>

Но если у какого-либо объекта нет реализации для извлечения атрибутов расширения, мы всегда будем получать значение null, и каждый раз, при получении атрибута расширения, нам нужно проверять, получили ли мы null, — если да, то их необходимо создавать. Чтобы избежать дублирования кода, нам нужно создать плагин afterGet для нашего объекта с атрибутами расширения.

Предположим, что у объекта продукта нет какой-либо реализации атрибутов расширения, поэтому наш плагин может выглядеть так:

use Magento\Catalog\Api\Data\ProductExtensionInterface;
use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Catalog\Api\Data\ProductExtensionFactory;

class ProductAttributesLoad
{
    /**
     * @var ProductExtensionFactory
     */
    private $extensionFactory;

    /**
     * @param ProductExtensionFactory $extensionFactory
     */
    public function __construct(ProductExtensionFactory $extensionFactory)
    {
        $this->extensionFactory = $extensionFactory;
    }

    /**
     * Loads product entity extension attributes
     *
     * @param ProductInterface $entity
     * @param ProductExtensionInterface|null $extension
     * @return ProductExtensionInterface
     */
    public function afterGetExtensionAttributes(
        ProductInterface $entity,
        ProductExtensionInterface $extension = null
    ) {
        if ($extension === null) {
            $extension = $this->extensionFactory->create();
        }

        return $extension;
    }
}

А теперь нужно привязать наш плагин к ProductInterface:

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Catalog\Api\Data\ProductInterface">
        <plugin name="ProductExtensionAttributeOperations" type="Magento\Catalog\Plugin\ProductAttributesLoad"/>
    </type>
</config>

Конфигурация расширенных атрибутов:

Для скалярных атрибутов мы можем использовать следующую конфигурацию:

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
    <extension_attributes for="Magento\Catalog\Api\Data\ProductInterface">
        <attribute code="first_custom_attribute" type="Magento\SomeModule\Api\Data\CustomDataInterface" />
        <attribute code="second_custom_attribute" type="Magento\SomeModule\Api\Data\CustomDataInterface" />
    </extension_attributes>
</config>

Для нескалярных атрибутов:

В первом случае мы получим следующий результат:

<product>
    <id>1</id>
    <sku>some-sku</sku>
    <custom_attributes><!-- Custom Attributes Data --></custom_attributes>
    <extension_attributes>
        <first_custom_attribute>1</first_custom_attribute>
        <second_custom_attribute>2</second_custom_attribute>
    </extension_attributes>
</product>

Во втором:

<product>
    <id>1</id>
    <sku>some-sku</sku>
    <custom_attributes><!-- Custom Attributes Data --></custom_attributes>
    <extension_attributes>
        <our_custom_data>
                <first_custom_attribute>1</first_custom_attribute>
                <second_custom_attribute>2</second_custom_attribute>
        </our_custom_data>
    </extension_attributes>
</product>

Добавить комментарий

Ваш адрес email не будет опубликован.

два × 2 =