I am currently developing a module working with the product edit in the backend. Its purpose is to retrieve categories the product belongs to and populate an attribute (the
In case you need to prevent the save method to execute for a core model (i.e. Catalog/Product), you can use reflection to set "$_dataSaveAllowed" to 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;
}
One of the possible approaches can be this one as well - it's a hack though
Mage::app()->getRequest()->setPost("YOUR_KEY",false);
I don't think you can you stop execution the way you want via an observer, Magento doesn't pay attention to anything that you might return or set via your observer.
One idea would be too rewrite the save method of the product model. You could check for any error flag that you set in your observer and then prevent the save from that point. Something like this:
function save()
{
if( $error_detection )
{
return $this;
}
else
{
return parent::save();
}
}
It's always a crap shoot as to which sections of Magento support this, but throwing an exception is often the prescribed way of telling Magento that something went wrong. The layers higher up the stack are set to catch these exceptions and use them to go back to the form and display an error message. Give this a try
Mage::throwException(Mage::helper('adminhtml')->__('You totally failed at that.'));
If you take a look at the Adminhtml
module's Catalog/ProductController.php
(1.5, but I'd assume a similar format in previous versions)
function saveAction()
{
...
$product = $this->_initProductSave();
try {
$product->save();
$productId = $product->getId();
...
}
The _initProductSave
method is where the catalog_product_prepare_save
event is fired. Since this is outside the saveAction
's try/catch block, the exception won't be caught (as described in the comments below).
You'll need to move you validation code into the product model's before save event (catalog_product_save_before
). Doing that should let you throw an exception and have the admin display the error message and represent the form for editing.
A couple of thoughts. Do you actually want to stop the save, or would "undoing" the changes be enough? If your observer detects that the required information is missing, then just iterate through the changed data and set it back to the original and allow the save to proceed. You should be able to do $product->getOrigData()
to compare which has changed?
Alternatively, why not make the category attribute mandatory? You should be able to do that in your config xml (not exactly sure how off the top of my head)
Finally, you could bind to the controller_action_predispatch_catalog_product_save
Event instead, and if you detect the error state, set a no-dispatch
flag, add your error message to the session and redirectReferrer. Check out my earlier answer here for details.
=========EDIT=========
I found a new way. In your Observer, change the _dataSaveAllowed
value on the object to false
. Mage_Core_Model_Abstract::save()
checks that value before proceeding with the save.
HTH,
JD