Остановка процесса сохранения продукта в наблюдателе - PullRequest
4 голосов
/ 24 марта 2011

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

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

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

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

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

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

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

-> Остальное

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

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

Вот пример моего файла 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;
        }
    }
}

Ответы [ 5 ]

15 голосов
/ 25 марта 2011

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

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

Если вы посмотрите на Catalog/ProductController.php модуля Adminhtml (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). Это должно позволить вам выбросить исключение, и администратор отобразит сообщение об ошибке и представит форму для редактирования.

2 голосов
/ 25 марта 2011

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

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

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

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

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

HTH,
JD

1 голос
/ 24 июня 2016

Если вам нужно запретить выполнение метода сохранения для базовой модели (т. Е. Каталога / продукта), вы можете использовать отражение, чтобы установить для "$ _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;
}
0 голосов
/ 06 марта 2013

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

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

0 голосов
/ 25 марта 2011

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

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

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