Php 在观测器中停止产品保存过程
我目前正在开发一个在后端使用产品编辑的模块。 其目的是检索产品所属的类别,并使用选定类别的列表填充属性(品牌属性) 管理员必须至少选择一个类别。 我的模块按预期工作,但如果管理员在编辑产品时未选择任何类别,我不知道如何停止保存过程 这是工作流程Php 在观测器中停止产品保存过程,php,magento,save,observer-pattern,abort,Php,Magento,Save,Observer Pattern,Abort,我目前正在开发一个在后端使用产品编辑的模块。 其目的是检索产品所属的类别,并使用选定类别的列表填充属性(品牌属性) 管理员必须至少选择一个类别。 我的模块按预期工作,但如果管理员在编辑产品时未选择任何类别,我不知道如何停止保存过程 这是工作流程 管理员在“产品编辑”页面的“类别”选项卡中选择类别 管理员点击“保存” 我的模块“观察”并收集所有类别 -->如果有选定的类别 我的模块的观察者做了一些事情来更新品牌属性 -->否则 我的模块的观察者向管理会话添加了一个错误 我的模块观察员应该
- 管理员在“产品编辑”页面的“类别”选项卡中选择类别
- 管理员点击“保存”
- 我的模块“观察”并收集所有类别
- 我的模块的观察者做了一些事情来更新品牌属性
- 我的模块的观察者向管理会话添加了一个错误
- 我的模块观察员应该告诉Magento停止保存产品。但是我该怎么做呢
<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>
我不认为你可以通过观察者以你想要的方式停止执行,Magento不会注意你可能通过观察者返回或设置的任何内容 一个想法是重写产品模型的save方法。您可以检查在观察者中设置的任何错误标志,然后从该点阻止保存。大概是这样的:
function save()
{
if( $error_detection )
{
return $this;
}
else
{
return parent::save();
}
}
关于Magento的哪些部分支持这一点总是一个废话,但是抛出异常通常是告诉Magento出了问题的规定方式。堆栈上层的层被设置为捕捉这些异常,并使用它们返回表单并显示错误消息。试试这个
Mage::throwException(Mage::helper('adminhtml')->__('You totally failed at that.'));
如果您看一下Adminhtml
模块的目录/ProductController.php
(1.5,但在以前的版本中我会采用类似的格式)
\u initProductSave
方法是触发catalog\u product\u prepare\u save
事件的位置。由于这在saveAction
的try/catch块之外,因此不会捕获异常(如下面的注释所述)
您需要将验证代码移动到产品模型的“保存前”事件中(
catalog\u product\u save\u before
)。这样做应该可以让您抛出一个异常,让管理员显示错误消息并表示要编辑的表单 一些想法。您真的想停止保存,还是“撤消”更改就足够了?如果您的观察者检测到缺少所需的信息,则只需迭代更改的数据并将其设置回原始数据,然后继续保存。您应该能够执行$product->getOrigData()
来比较哪些更改了
或者,为什么不强制使用category属性呢?您应该能够在您的配置xml中实现这一点(不完全确定我的想法有多离谱)
最后,您可以绑定到controller\u action\u predispatch\u catalog\u product\u save
事件,如果检测到错误状态,请设置no dispatch
标志,将错误消息添加到会话并重定向referer。查看我先前的答案了解详细信息
============================
我找到了一条新路。在观察者中,将对象上的\u dataSaveAllowed
值更改为false
Mage\u Core\u Model\u Abstract::save()
在继续保存之前检查该值
HTH,JD一种可能的方法也可以是这种方法——尽管这是一种黑客攻击
Mage::app()->getRequest()->setPost(“您的_键”,false)代码>如果需要阻止对核心模型(即目录/产品)执行保存方法,可以使用反射将“$\u 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会在这种情况下捕获抛出的异常。虽然我可能错了。我也同意,不会走这条路:)绝对值得一试。我查看了Mage_Catalog_Model_产品、其父类和相关资源类的\u beforeSave()
方法,但在继续保存之前,它们没有检查任何异常:(伙计们,我尝试了,结果“失败”因为它会在一个漂亮的错误报告页面上抛出异常,而不是在产品编辑页面上重新加载“You All failed”消息。非常感谢。我会继续挖掘,并让你知道我是否成功!@vrnet我进一步研究了这个问题,并用更多信息更新了答案。如果你在活动前将验证移至目录“产品”保存“你应该被设置。vrnet::getHappiness('applauses')->thankAlanTonsOfTimes()-这太棒了!非常感谢!nano唯一的缺点是在重新加载时不会保留产品版本中的数据。管理员必须重新键入所有信息…他/她会小心下一个产品:)再次感谢。@vrnet保留您可以调用的数据Mage::getSingleton('adminhtml/session')->set[MODULE]data($this->getData())在模型中抛出异常之前,调用$form->setValues(Mage::getSingleton('adminhtml/session')->get[MODULE]Data())
在Form.phpHey Jonathan中的\u prepareForm
函数的末尾-非常感谢,但Magento似乎并不关心no分派。我已经甩了M
function saveAction()
{
...
$product = $this->_initProductSave();
try {
$product->save();
$productId = $product->getId();
...
}
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;
}