4

我目前正在开发一个与后端产品编辑一起使用的模块。其目的是检索产品所属的类别并使用所选类别列表填充属性(品牌属性)。

管理员必须选择至少一个类别。

我的模块按预期工作,只是如果管理员在编辑产品时没有选择任何类别,我不知道如何停止保存过程。

这是工作流程

  • 管理员在产品编辑页面的类别选项卡中选择类别
  • 管理员点击“保存”
  • 我的模块“观察”并收集所有类别

--> 如果有选择的类别

  • 我的模块的观察者做它的东西来更新品牌属性

--> 其他

  • 我的模块的观察者向管理会话添加了一个错误
  • 我的模块的观察者应该告诉 Magento 停止保存产品。但我该怎么做呢?

一般的问题可能是:如何将“停止保存”参数传递给观察者?

这是我的 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>

观察者.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;
        }
    }
}
4

5 回答 5

15

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是触发事件的地方。由于这是在saveActiontry/catch 块之外,因此不会捕获异常(如下面的评论中所述)。

您需要在保存事件 ( catalog_product_save_before) 之前将验证代码移动到产品模型中。这样做应该让您抛出异常并让管理员显示错误消息并表示要编辑的表单。

于 2011-03-24T22:03:13.780 回答
2

几个想法。您真的要停止保存,还是“撤消”更改就足够了?如果您的观察者检测到缺少所需的信息,则只需遍历更改的数据并将其设置回原始数据并允许保存继续。你应该可以$product->getOrigData()对比一下哪个变了?

或者,为什么不强制类别属性?你应该能够在你的配置 xml 中做到这一点(不完全确定我的想法)

最后,您可以改为绑定到controller_action_predispatch_catalog_product_save事件,如果您检测到错误状态,设置一个no-dispatch标志,将您的错误消息添加到会话并重定向Referrer。在此处查看我之前的答案以获取详细信息。

=========编辑=========

我找到了一种新方法。在您的观察者中,_dataSaveAllowed将对象上的值更改为false. Mage_Core_Model_Abstract::save()在继续保存之前检查该值。

HTH,
法学博士

于 2011-03-25T01:46:23.727 回答
1

如果您需要阻止对核心模型(即目录/产品)执行保存方法,可以使用反射将“$_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;
}
于 2016-06-24T16:34:47.783 回答
0

我认为您不能通过观察者以您想要的方式停止执行,Magento 不会关注您可能通过观察者返回或设置的任何内容。

一种想法是重写产品模型的保存方法。您可以检查您在观察者中设置的任何错误标志,然后从那时起阻止保存。像这样的东西:

function save()
{
    if( $error_detection )
    {
        return $this;
    }
    else
    {
        return parent::save();
    }
}
于 2011-03-24T21:45:24.110 回答
0

一种可能的方法也可以是这种方法-尽管它是一种技巧

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

于 2013-03-06T18:17:57.927 回答