Perbedaan antara catalog_product_save_after dan catalog_product_save_commit_after?

8

Adakah yang bisa menjelaskan perbedaan antara peristiwa ini. Tolong, cepat dan kotor saja. Terima kasih.

Saya memiliki metode Pengamat seperti:

public function detectProductChanges($observer)
    {
        $product = $observer->getProduct();
        $old = $product->getOrigData();
        $new = $product->getData();
        if ($product->hasDataChanges() && $old['status'] == 1 && $new['status'] == 2) {
            $this->_sendStatusMail($product);
        }
    }

Itu tidak sampai ke sendStatusMail()

Saya mengaitkan ke acara:

        <events>
            <catalog_product_save_after>
                <observers>
                    <productchange>
                        <type>singleton</type>
                        <class>A_ProductNotification_Model_Observer</class>
                        <method>detectProductChanges</method>
                    </productchange>
                </observers>
            </catalog_product_save_after>
        </events>

Haruskah saya menggunakan: catalog_product_save_commit_after

TUJUAN:

Minta email dikirim setelah produk dinonaktifkan.

private function _sendStatusMail($product)
    {
        if (!Mage::getStoreConfig('trans_email/ident_custom3/email')) return false;
        $emailTemplate = Mage::getModel('core/email_template');
        $emailTemplate->loadDefault('elec_productnotification_tpl');
        $emailTemplate->setTemplateSubject('Product has been disabled');
        $emailTemplate->setSenderEmail($salesData['email']);
        $emailTemplateVariables['style_number']   = $product->getElecStyle();
        $emailTemplateVariables['frame_color']    = $product->getAttributeText('frame_color');
        $emailTemplateVariables['size']           = $product->getAttributeText('size');
        $emailTemplateVariables['elec_color'] = $product->getAttributeText('elec_color');
        $emailTemplateVariables['store_name']   = Mage::getModel('core/store')->load($product->getStoreId())->getName();
        $emailTemplateVariables['product_name'] = Mage::getModel('catalog/product')->load($product->getId())->getName();
        $emailTemplateVariables['product_sku']  = $product->getSku();
        $emailTemplateVariables['dates']        = date("F jS Y h:i:sA", strtotime('-7 hours'));
        // Get General email address (Admin->Configuration->General->Store Email Addresses)
        $emails = explode(',', Mage::getStoreConfig('trans_email/ident_custom3/email'));
        foreach ($emails as $email) $emailTemplate->send($email, $product->getStoreId(), $emailTemplateVariables);
    }
}
metode ini
sumber
Anda harus menggunakan acara <catalog_product_status_update>
Nickool
Apakah itu alasannya mengapa tidak menembak? Cukup menggunakan acara yang salah? @Nickool
metode ini

Jawaban:

14

Penghematan terjadi dalam transaksi MySQL dan save_afteracara tersebut dipicu sebelum transaksi dilakukan, sehingga Anda dapat melakukan pembaruan tambahan dalam database dalam transaksi yang sama.

The save_commit_afterevent dipicu setelah transaksi telah dilakukan, yaitu ketika perubahan ditulis ke database.

Selain itu, aktif save_commit_after, _hasDataChangesproperti sudah disetel ulang false, jadi cek Anda tidak akan berfungsi. Di sisi lain, jika tidak ada perubahan, kedua peristiwa bahkan tidak akan dipicu, karena Mage_Core_Model_Abstract :: save () tidak melakukan apa-apa jika tidak ada perubahan data:

if (!$this->_hasModelChanged()) {
    return $this;
}

Yang sedang berkata, saya tidak melihat mengapa kode Anda seharusnya tidak berfungsi.

Fabian Schmengler
sumber
Terima kasih atas jawabannya. Ketika saya menambahkan Mage :: log () di tempat sendStatusMail () saya mendapatkan pesan log dengan benar. Tapi itu tidak mengirim email. Saya memastikan bahwa "Nonaktifkan Komunikasi Email" diatur ke TIDAK dan alamat email saya ada di email khusus> alamat email toko saya. Ada ide lain mengapa itu tidak berhasil? @fschmengler
metode ini
Tanpa mengetahui metode sendStatusMail Anda, tidak. Itu mungkin bahan untuk pertanyaan lain. Atau apakah metode yang sama berfungsi jika dipanggil dari konteks yang berbeda?
Fabian Schmengler
Saya memperbarui pertanyaan awal saya untuk menunjukkan metode sendStatusMail. Jika Anda tidak keberatan untuk membantu lebih lanjut. Terima kasih.
metode ini
Adakah kesempatan Anda bisa memberi saya pendapat Anda tentang metode sendStatusMail ($ produk) saya?
metode ini
Saya tidak dapat menemukan kesalahan di sana, maaf
Fabian Schmengler
0

vendor / magento / framework / Model / ResourceModel / Db / AbstractDb.php

public function save(\Magento\Framework\Model\AbstractModel $object)
{
    // ...

    $this->beginTransaction();

    try {
        // ...
        if ($object->isSaveAllowed()) {
            // ...
            $this->_beforeSave($object);
            // ...
            if ($this->isObjectNotNew($object)) {
                $this->updateObject($object);
            } else {
                $this->saveNewObject($object);
            }
            // ...
            $this->processAfterSaves($object);
        }
        $this->addCommitCallback([$object, 'afterCommitCallback'])->commit();
        // ...
    } catch (\Exception $e) {
        $this->rollBack();
        $object->setHasDataChanges(true);
        throw $e;
    }
    return $this;
}

Mari kita lihat entitas produk tabungan.

-product_model save
|-product_resource save
|--begin transaction (0 lvl)
|---before product save events
|---creating new product or updating existing one
|---after product save events
|----one of event is saving another entity CatalogInventory Stock
|-----catalog_inventory_stock resource save
|------begin another transaction (1 lvl)
|-------before stock save events
|-------updating / creating stock item
|-------after product save events (here could be one more 
        dependable entity which could cause one more save
        operation and begin another transaction)
|------commit of 1st level !!! No callbacks executed
|--commit of 0 level ALL CALLBACKS ARE EXECUTED

Berikut adalah kode fungsi komit:

/**
 * Commit resource transaction
 *
 * @return $this
 * @api
 */
public function commit()
{
    $this->getConnection()->commit();
    /**
     * Process after commit callbacks
     */
    if ($this->getConnection()->getTransactionLevel() === 0) {
        $callbacks = CallbackPool::get(spl_object_hash($this->getConnection()));
        try {
            foreach ($callbacks as $callback) {
                call_user_func($callback);
            }
        } catch (\Exception $e) {
            $this->getLogger()->critical($e);
        }
    }
    return $this;
}

Mari kita lihat contoh kita lebih dekat.

  1. $this->getConnection()->commit();masukkan nilai ke dalam DB untuk level 1 kami (ini Stock). Jika sesuatu yang buruk terjadi di sini, pengecualian akan dilemparkan dan semua perubahan akan dibatalkan.

  2. Kemudian ia pergi untuk memproses panggilan balik. Karena kita saat ini di level 1, tidak ada panggilan balik yang akan dipanggil. Dan kami pindah dari catalog_product_after_save acara untuk melakukan perubahan produk (0 level).

  3. $this->getConnection()->commit();memasukkan nilai ke dalam DB untuk level 0 kami (itu Produk itu sendiri). Jika sesuatu yang buruk terjadi di sini pengecualian juga akan dibuang dan semua perubahan juga akan dibatalkan.

  4. Kemudian kami akan beralih ke eksekusi callback. Sekarang kita berada di level 0 dan callback akan dijalankan. Apa pun di dalam diri Anda yang buruk call_user_func($callback);akan ditangkap dan baru saja dicatat. Tidak ada yang akan dibatalkan jika panggilan balik menyebabkan pengecualian

zhartaunik
sumber