Akeneo 2.2.8: Как мне получить исходные данные атрибута в событии akeneo.storage.pre_save?

Я использую Akeneo 2.2.8 и пытаюсь использовать akeneo.storage.pre_save-event для сравнения исходных данных о продукте с новыми предоставленными данными. Я делаю это, подписываясь на akeneo.storage.pre_save-событие:

In event_subscribers.yml:

parameters:
    vendor.bundle.event_subscriber.product_save.class: Vendor\Bundle\CustomBundle\EventSubscriber\ProductSaveSubscriber

services:
    vendor.bundle.event_subscriber.product_save:
        class: '%vendor.bundle.event_subscriber.product_save.class%'
        arguments:
            - '@pim_catalog.repository.product'
        tags:
            - { name: kernel.event_listener, event: akeneo.storage.pre_save, method: onPreSave, priority: 255 }

In ProductSaveSubscriber.php:

/**
 * @var ProductRepositoryInterface
 */
protected $productRepository;

public function __construct(ProductRepositoryInterface $productRepository)
{
    $this->productRepository = $productRepository;
}

public function onPreSave(GenericEvent $event)
{
    /** @var Product $subject */
    $subject = $event->getSubject();

    if ($subject instanceof Product) {

        $originalProduct = $this->productRepository->findOneByIdentifier($subject->getIdentifier());

        foreach ($subject->getAttributes() as $attribute) {
            if ($attribute->getReadOnly()) {
                echo "{$attribute->getCode()} : {$subject->getValue($attribute->getCode())}\n";
                echo "{$attribute->getCode()} : {$originalProduct->getValue($attribute->getCode())}\n";
            }
        }
    }
}

Теперь, когда я запускаю этот код, я ожидаю, что второй оператор echo предоставит исходные данные (поскольку я загрузил их заново). Однако исходный продукт, который я загружаю из репозитория, также содержит новые данные.

Также следует отметить, что если я добавлю die()-оператор, данные не сохранятся в базе данных. Получается, что репозиторий возвращает модель в памяти или что-то в этом роде.

Может кто-то указать мне верное направление? Или я использую неправильный подход для сравнения вновь введенных данных с уже существующими?


person Giel Berkers    schedule 18.06.2018    source источник


Ответы (1)


Теперь, когда я запускаю этот код, я ожидаю, что второй оператор echo предоставит исходные данные (поскольку я загрузил их заново). Однако исходный продукт, который я загружаю из репозитория, также содержит новые данные.

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

Также следует отметить, что если я добавлю оператор die (), данные не сохранятся в базе данных. Получается, что репозиторий возвращает модель в памяти или что-то в этом роде.

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

  • Создано событие PRE_SAVE
  • COMMIT / FLUSH
  • Создано событие POST_SAVE

Поэтому, если вы вызываете die во время события PRE_SAVE, COMMIT / FLUSH не вызывается.

Может кто-то указать мне верное направление? Или я использую неправильный подход для сравнения вновь введенных данных с уже существующими?

Я не знаю вашего конкретного варианта использования, но вы можете использовать функцию запроса (см. https://github.com/akeneo/pim-community-dev/blob/2.2/src/Pim/Bundle/CatalogBundle/Doctrine/ORM/Query/FindAttributesForFamily.php). Его цель - напрямую получить из базы данных необходимые данные (это будет исходное значение, поскольку продукт не был сброшен в базу данных на PRE_SAVE).

Надеюсь, это поможет.

person SamirBoulil    schedule 21.06.2018
comment
Спасибо за ответ. Я уже подозревал, что это был способ Doctrines обрабатывать записи, при которых репозиторий не возвращал ожидаемого результата. Тем временем я решил свой конкретный вариант использования, используя декоратор для контроллера (это был лучший подход, потому что событие также запускалось для импорта или обновления API, что было нежелательно). Я буду помнить ваше предложение, когда мне понадобится запрашивать материал в будущем. - person Giel Berkers; 21.06.2018