catalog_product_save_after Ereignis für die Massage

7

Ich verwende das Ereignis catalog_product_save_after, um eine Aktion auszulösen, nachdem ein Produkt geändert / gespeichert wurde. Dieses Ereignis funktioniert nicht, wenn eine Massaktion zum Ändern des Produkts verwendet wird, da dies ohne Aufruf von save () erfolgt.

  • Gibt es ein anderes Ereignis, mit dem Produktänderungen überwacht werden können?
  • Gibt es einen empfohlenen Weg, um alle Produktänderungen zu erhalten?
Wienczny
quelle

Antworten:

5

Sie können diesen Job über Standardereignisse / Beobachter ausführen:

<global>
     <events>
        <catalog_product_save_before>
            <observers>
                <some_module_detect_product_changes>
                    <type>singleton</type>
                    <class>some_module/observer</class>
                    <method>detectProductChanges</method>
                </some_module_detect_product_changes>
            </observers>
        </catalog_product_save_before>
        <catalog_product_attribute_update_before>
            <observers>
                <some_module_detect_product_attribute_changes>
                    <type>singleton</type>
                    <class>some_module/observer</class>
                    <method>detectProductAttributeChanges</method>
                </some_module_detect_product_attribute_changes>
            </observers>
        </catalog_product_attribute_update_before>
</global>

Und Observer.php:

class Some_Module_Model_Observer{
    public function detectProductAttributeChanges($observer)
    {
        $attributesData = $observer->getEvent()->getAttributesData();
        $productIds     = $observer->getEvent()->getProductIds();

        $user  = Mage::getSingleton('admin/session')->getUser();
        foreach ($productIds as $id) {
            $change             = Mage::getModel('some_module/changes');
            $change->product_id = $id;
            $change->new_values = print_r($attributesData, true);
            $change->user_id    = ($user) ? $user->getId() : NULL;
            $change->created    = now();
            $change->save();
        }
        return $this;
    }

    public function detectProductChanges($observer)
    {
        /**
         * @var $product Mage_Catalog_Model_Product
         * @var $user    Mage_Admin_Model_User
         */
        $product = $observer->getEvent()->getProduct();
        if ($product->hasDataChanges()) {

            try {
                $user       = Mage::getSingleton('admin/session')->getUser();
                $attributes = $this->getAttributes();
                $new        = array();
                $org        = array();
                $changes    = array();
                foreach ($attributes as $attribute) {
                    if (!is_array($product->getData($attribute))) {
                        $new[$attribute] = ($product->getData($attribute)) ? $product->getData($attribute) : null;
                        if (!is_array($product->getOrigData($attribute))) {
                            $org[$attribute] = ($product->getOrigData($attribute)) ? $product->getOrigData($attribute) : null;
                            if (($new[$attribute] != $org[$attribute])) {
                                $changes[$attribute] = array('new'=> $new[$attribute],
                                                             'old'=> $org[$attribute]);
                            }
                        }
                    }
                }

                $stokAttributes = array(
                    'qty',
                    'manage_stock',
                    'is_in_stock',
                    'min_qty',
                    'min_sale_qty',
                    'max_sale_qty',
                );
                if ($product->getStockItem()) {
                    foreach ($stokAttributes as $attribute=> $value) {
                        $new[$attribute] = ($product->getStockItem()->getData($attribute)) ? $product->getStockItem()->getData($attribute) : null;
                        $org[$attribute] = ($product->getStockItem()->getOrigData($attribute)) ? $product->getStockItem()->getOrigData($attribute) : null;
                        if ($new[$attribute] != $org[$attribute]) {
                            $changes[$attribute] = array('new'=> $new[$attribute],
                                                         'old'=> $org[$attribute]);
                        }
                    }
                }


                $newValues = array_intersect_key($new, $changes);
                if (count($newValues)) {
                    $oldValues = array_intersect_key($org, $changes);

                    $change             = Mage::getModel('some_module/changes');
                    $change->product_id = $product->entity_id;
                    $change->sku        = $product->sku;
                    $change->name       = $product->name;
                    $change->new_values = print_r($newValues, true);
                    $change->old_values = print_r($oldValues, true);
                    $change->user_id    = ($user) ? $user->getId() : NULL;
                    $change->created    = now();
                    $change->save();
                }
            } catch (Exception $e) {
                Mage::log($e->getTraceAsString(), null, 'product_changes_fault.log');
            }
        }
        return $this;
    }

}

Hier habe ich das Änderungsmodell verwendet, um alle Änderungen in der Datenbank zu speichern. Sie können auch ein Administratorraster erstellen, um nachverfolgte Änderungen im Dashboard anzuzeigen.

mageUz
quelle
Dies ist eine wirklich gute Antwort, aber es gibt ein kleines Problem: Ich muss die Produkte erhalten, nachdem sie gespeichert wurden. Die aufgezeichneten Änderungen können verwendet werden, um die Produkte in einen Cron-Job zu laden, aber der Cron-Job wird nur alle paar Minuten ausgeführt. Die Änderungen könnten auch in controller_front_send_response_after verarbeitet werden (auch ohne sie in db zu speichern), aber ich denke, dies wäre eine hässliche Lösung.
Wienczny
Ich kann mir nicht vorstellen, was du wirklich willst. Wenn Sie Produktänderungen über einen Cron-Job verfolgen möchten, können Sie dies auch tun. Sie benötigen jedoch eine zusätzliche Tabelle zum Speichern alter und neuer Werte. Wenn Sie nur einige Attribute verfolgen möchten, können Sie in jedem bestimmten Zeitraum und einen Schnappschuss erstellen Vergleichen Sie einen Schnappschuss mit einem neuen Schnappschuss. Auf diese Weise können Sie Änderungen erkennen. Wenn Sie jedoch ganze Attribute verfolgen möchten, ist das Speichern von Änderungen komplizierter und teurer.
MagierUz
Eine einfache Möglichkeit besteht darin, den Hash-Code des Produkts anhand der Attribute zu berechnen, die Sie verfolgen möchten. Ex:. $ hash = md5 ($ product-> getName (). $ product-> getPrice (). $ product-> getSomeValueYouWantToTrack ()); Wenn ($ product-> getHashCode ()! = $ hash) {// Produkt Änderungen hat, mache eine Logik}; $ product-> setHashCode ($ hash) -> save ()
mageUz
Ich möchte keine Produktänderungen verfolgen, sondern geänderte Produkte. Die geänderten Produkte müssen mit dem externen Service synchronisiert werden.
Wienczny
Siehe meine neue letzte Antwort oben gegeben
mageUz
4

Durch Beobachten von catalog_product_attribute_update_before , das von mageUz aufgerufen wurde, können Sie die betroffenen entity_ids, auf die das Ereignis verweist, als product_ids speichern:

Durch Zend_Debug :: Dumping eines $ Observer-> getEvent () -> getData (), in dem ich catalog_product_attribute_update_ behandelt habe, bevor ich Folgendes erhalten habe:

Array (4) {
  ["attribute_data"] => & array (1) {
    ["status"] => int (1)
  }}
  ["product_ids"] => & array (2) {
    [0] => Zeichenfolge (6) "159340"
    [1] => Zeichenfolge (6) 159339
  }}
  ["store_id"] => & int (0)
  ["name"] => string (39) "catalog_product_attribute_update_before"
}}

Sie können diese entity_ids beispielsweise im Magento-Sitzungs-Singleton speichern.

Beobachten Sie dann end_process_event_catalog_product_mass_action , eines der dynamisch erstellten Ereignisse von Magento. Die Behandlung zeigt an, wann die Produktänderungen abgeschlossen sind, sodass Sie den aktualisierten Produktstatus abrufen können. Da es selbst keine Daten enthält, benötigen Sie die gerade gespeicherten entity_ids.

Regelmäßig geplante Programmierung
quelle
0

Ich habe bereits eine angemessene Logik für Ihre Situation kommentiert. Aber um dich zu verstehen, gebe ich weiteren Code:

class Some_Module_Model_Sync{
public function catalogSynchronizeChangedProducts()
{
    /**
     * suppose you have hash_code attribute for catalog products which is store
     * hash code of synchronizeable attribute values.
     */
    $collection = Mage::getResourceModel('catalog/product_collection');
    foreach ($collection as $product) {
        $hash = md5($product->getName() . $product->getPrice() . $product->getSomeValueYouWantToSyncronize());
        if ($product->getHashCode() != $hash) {
            //if you understand this stuff, product has some changes, because of
            //new hash code not equal to hash code when last synchronized time;
            //you should synchronize this product

            /*after synchronization */
            $product->setHashCode($hash)->save();
        }
    }
}
}

Und Ihr Cron verwendet diese Logik, um Ihre Produkte zu synchronisieren.

mageUz
quelle