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


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

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

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

Вот рабочий процесс

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

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

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

-->Остальное

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

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

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

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

Config.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>

Observer.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;
        }
    }
}
Author: Jonathan Day, 2011-03-24

5 answers

Всегда сложно решить, какие разделы 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. Поскольку это находится за пределами блока saveAction try/catch, исключение не будет поймано (как описано в комментариях ниже).

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

 15
Author: Alan Storm, 2011-03-25 14:51:17

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

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

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

========= РЕДАКТИРОВАТЬ=========

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

HTH,
Джей Ди

 2
Author: Jonathan Day, 2017-05-23 10:29:08

В случае, если вам нужно запретить выполнение метода сохранения для базовой модели (т.Е. Каталога/продукта), вы можете использовать отражение, чтобы установить значение "$_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;
}
 1
Author: José Romero, 2016-06-24 16:34:47

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

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

function save()
{
    if( $error_detection )
    {
        return $this;
    }
    else
    {
        return parent::save();
    }
}
 0
Author: Josh, 2011-03-24 21:45:24

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

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

 0
Author: srgb, 2013-03-06 18:17:57