Остановка процесса сохранения продукта в наблюдателе


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

Администратор обязан выбрать хотя бы одну категорию.

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

Здесь является ли рабочий процесс

  • администратор выбирает категории на вкладке категория страницы редактирования продукта
  • администратор нажимает на кнопку "Сохранить"
  • мой модуль "наблюдает" и собирает все категории

--> Если есть выбранные категории

  • наблюдатель моего модуля делает все возможное, чтобы обновить атрибут бренда

--> Else

  • наблюдатель моего модуля добавляет ошибку в сеанс администрирования
  • наблюдатель моего модуля должен сказать Magento, чтобы остановить сохранение продукта. Но как мне это сделать ?

Общий вопрос, возможно, будет таким : как передать аргумент" остановить сохранение " наблюдателю ?

Вот пример моей конфигурации.xml-файл и метод, который имеет дело с рабочим процессом, я объяснил выше.

Большое Спасибо за вашу помощь и получайте удовольствие Magentoing !

Конфиг.xml

    <catalog_product_prepare_save>
        <observers>
            <brands_product_save_observer>
                <type>singleton</type>
                <class>brands/observer</class>
                <method>saveProductBrand</method>
            </brands_product_save_observer>
        </observers>
    </catalog_product_prepare_save>

Наблюдатель.php

public function saveProductBrand($observer) {
    $product = $observer->getProduct();
    $categoryIds = $product->getCategoryIds();
    if (isset($categoryIds)) {
        foreach ($categoryIds as $categoryId) {
            $isBrandCategory = Mage::getModel('brands/navigation')->isBrandCategory($categoryId);
            if ($isBrandCategory)
                $brandCategories[] = $categoryId;
        }
        if (isset($brandCategories)) {
            $brandId = Mage::getModel('brands/navigation')->getBrand($brandCategories[0]);
            if ($brandId) {
                $attribute = Mage::getModel('eav/config')->getAttribute('catalog_product', 140);
                foreach ($attribute->getSource()->getAllOptions(true, true) as $option) {
                    $attributeArray[$option['label']] = $option['value'];
                }
                $categoryName = Mage::getModel('catalog/category')->load($brandId)->getName();
                $product->setData('brand', $attributeArray[$categoryName]);
            }
        } else {
            Mage::getSingleton('adminhtml/session')->addError(Mage::helper('catalog')->__('Please add this product to a brand in the "Categories" tab.'));

            HERE SOME CODE TO TELL MAGENTO TO STOP SAVING THE PRODUCT

            return;
        }
    }
}
5 4

5 ответов:

Это всегда дерьмо стрелять о том, какие разделы Magento поддерживают это, но бросать исключение часто предписанный способ сказать Magento, что что-то пошло не так. Слои, расположенные выше по стеку, настроены так, чтобы перехватывать эти исключения и использовать их для возврата к форме и отображения сообщения об ошибке. Дайте этому попытку

Mage::throwException(Mage::helper('adminhtml')->__('You totally failed at that.'));

Если вы посмотрите на модуль Adminhtml Catalog/ProductController.php (1.5, но я бы предположил аналогичный формат в предыдущих версиях)

function saveAction()
{
    ...
    $product = $this->_initProductSave();

    try {
        $product->save();
        $productId = $product->getId();
    ...
}

Метод _initProductSave где событие catalog_product_prepare_save запускается. Поскольку это находится за пределами блока try/catch saveAction, исключение не будет поймано (как описано в комментариях ниже).

Вам нужно будет переместить код проверки в модель продукта перед сохранением события (catalog_product_save_before). Это должно позволить вам создать исключение и заставить администратора отобразить сообщение об ошибке и представить форму для редактирования.

Пара мыслей. Вы действительно хотите остановить сохранение или достаточно будет "отменить" изменения? Если ваш наблюдатель обнаружит, что требуемая информация отсутствует, просто повторите изменение данных и установите его обратно в исходное состояние, а затем разрешите сохранение. Вы должны быть в состоянии сделать $product->getOrigData(), чтобы сравнить, что изменилось?

В качестве альтернативы, почему бы не сделать атрибут категории обязательным? Вы должны быть в состоянии сделать это в вашей конфигурации xml (не совсем уверен, как выкл макушка моей головы)

Наконец, вместо этого можно выполнить привязку к событию controller_action_predispatch_catalog_product_save, и если вы обнаружите состояние ошибки, установите флаг no-dispatch, Добавьте сообщение об ошибке в сеанс и redirectReferrer. Проверьте мой предыдущий ответ здесь для деталей.

=========править=========

Я нашел новый способ. В наблюдателе измените значение _dataSaveAllowed объекта на false. Mage_Core_Model_Abstract::save() проверяет это значение, прежде чем продолжить сохранение.

HTH,
JD

В случае, если вам нужно предотвратить выполнение метода save для базовой модели (т. е. каталога / продукта), вы можете использовать отражение, чтобы установить" $_dataSaveAllowed " в false:

public function catalogProductSaveBefore($observer)
{
    try {
        $product = $observer->getProduct();

        $reflectionClass = new ReflectionClass('Mage_Catalog_Model_Product');
        $reflectionProperty = $reflectionClass->getProperty('_dataSaveAllowed');
        $reflectionProperty->setAccessible(true);
        $reflectionProperty->setValue($product, false);
    } catch (Exception $e) {
            Mage::log($e->getMessage());
    }

    return $this;
}

Я не думаю, что вы можете остановить выполнение так, как вы хотите через наблюдателя, Magento не обращает внимания ни на что, что вы можете вернуть или установить через своего наблюдателя.

Одной из идей было бы слишком переписать метод сохранения модели продукта. Вы можете проверить наличие любого флага ошибки, установленного в вашем наблюдателе, а затем предотвратить сохранение с этой точки. Что-то вроде этого:

function save()
{
    if( $error_detection )
    {
        return $this;
    }
    else
    {
        return parent::save();
    }
}

Одним из возможных подходов может быть и этот-это хак, хотя

Mage::app()->getRequest()->setPost("YOUR_KEY",false);