Get product changes


北战南征 提交于 2019-12-04 19:33:13

问题


Situation is:

Admin logs in to system and he changes product somehow.

For example:

Sets qty to 10 Adds 2 images Changes description

Is there any way to track these changes? Well I mean exactly track WHAT and HOW admin changed?

I use Magento CE 1.6


回答1:


You can find the unaltered data through an object's getOrigData() method. A good time to get the object is through it's save_before event, so create an observer for the catalog_product_save_before event. The observer might contain the following:

public function onCatalogProductSaveBefore($observer)
{
  $product = $observer->getProduct();
  if ($product->hasDataChanges()) {
    $newValues = array_diff_assoc($product->getData(), $product->getOrigData());
    $oldValues = array_diff_assoc($product->getOrigData(), $product->getData());
    $added     = array_diff_key($product->getData(), $product->getOrigData());
    $unset     = array_diff_key($product->getOrigData(), $product->getData());
  }
}

Note that $newValues will include all of $added and existing attributes that have had their value changed. Ditto for $oldValues and $unset.




回答2:


Yes you can find unaltered data through getOrigData() as pointed out by clockworkgeek but Magento has a build in function to compare and check if the data has been changed. The method is called dataHasChangedFor() and you have to pass the property that you want to check. It would look somthing like this.

$isChanged = $productData->dataHasChangedFor('description'); 
if ($isChanged) { 
// do somthing 
}

here the method dataHasChanged() will return boolean value based on whether the data was altered.




回答3:


just in case some people still coming up to this one: @clockworkgeek's answer is not correct, as soon as you turn on developer mode and displaying errors (php>=5.4) you will get exceptions and warnings:

Array to string conversion in...

as solution for recursive comparison:

public function onCatalogProductSaveBefore($observer)
{
  $product = $observer->getProduct();
  if ($product->hasDataChanges()) {
    $newValues = $this->_compareArrayAssocRecursive($product->getData(), $product->getOrigData());
    $oldValues = $this->_compareArrayAssocRecursive($product->getOrigData(), $product->getData());
  }
}

protected function _compareArrayAssocRecursive($array1, $array2) 
{
    $diff = array();
    foreach ($array1 as $key => $value) {
        if (is_array($value)) {
            if (!isset($array2[$key]) || !is_array($array2[$key])) {
                $diff[$key] = $value;
            } else {
                $newDiff = $this->_compareArrayAssocRecursive($value, $array2[$key]);
                if (!empty($newDiff)) {
                    $diff[$key] = $newDiff;
                }
            }
        } elseif (!array_key_exists($key,$array2) || $array2[$key] !== $value) {
            $diff[$key] = $value;
        }
    }
    return $diff;
}

Hope that helps Personally i would recommend to put that function into a helper class and make it public :)

UPDATE: according to problems with numeric values was float and decimal the better solution would be:

/**
 * return diff according to product changes 
 * 
 * @param Mage_Catalog_Model_Product $product
 * @return array
 */
protected function _compareArrayAssocRecursive($product)
{
    $diff = array();
    $attributes = $product->getTypeInstance(true)->getEditableAttributes($product);

    foreach ($attributes as $key => $value) {
        if ($product->dataHasChangedFor($key)) {
            $diff[$key] = $product->getData($key);
        }
    }
    return $diff;
}


来源:https://stackoverflow.com/questions/8182009/get-product-changes

标签

工具导航Map