Sự khác biệt giữa catalog_product_save_after và catalog_product_save_commit_after?


8

Bất cứ ai có thể giải thích sự khác biệt giữa các sự kiện này. Chỉ cần nhanh chóng và bẩn xin vui lòng. Cảm ơn bạn.

Tôi có một phương thức Observer như vậy:

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);
        }
    }

Nó không đến được sendStatusMail()

Tôi đang tham gia vào sự kiện này:

        <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>

Tôi có nên sử dụng: catalog_product_save_commit_after

MỤC TIÊU:

Có một email được gửi sau khi sản phẩm bị vô hiệu hóa.

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);
    }
}

bạn nên sử dụng sự kiện <catalog_product_status_update>
Nickool

Đó có phải là lý do nó không bắn? Đơn giản là sử dụng sai sự kiện? @Nickool
thismethod

Câu trả lời:


14

Việc lưu xảy ra trong một giao dịch MySQL và save_aftersự kiện được kích hoạt trước khi giao dịch được cam kết, do đó bạn có thể thực hiện các cập nhật bổ sung trong cơ sở dữ liệu trong cùng một giao dịch.

Sự save_commit_afterkiện được kích hoạt sau khi giao dịch được thực hiện, tức là khi các thay đổi được ghi vào cơ sở dữ liệu.

Ngoài ra, trên save_commit_after, thuộc _hasDataChangestính đã được đặt lại false, vì vậy kiểm tra của bạn sẽ không hoạt động. Mặt khác, nếu không có thay đổi, cả hai sự kiện thậm chí sẽ không được kích hoạt, vì Mage_Core_Model_Abauge :: save () không làm gì nếu không có thay đổi dữ liệu:

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

Điều đó đang được nói, tôi không thấy lý do tại sao mã của bạn không hoạt động.


Cảm ơn bạn đã trả lời. Khi tôi thêm một Mage :: log () thay cho sendStatusMail () tôi nhận được thông điệp tường trình chính xác. Nhưng nó không gửi email. Tôi đảm bảo rằng "Vô hiệu hóa liên lạc email" được đặt thành KHÔNG và địa chỉ email của tôi nằm trong email tùy chỉnh> lưu địa chỉ email. Bất kỳ ý tưởng khác tại sao nó không hoạt động? @fschmengler
thismethod

Không biết phương thức sendStatusMail của bạn, không. Đó có lẽ là tài liệu cho một câu hỏi khác. Hoặc cùng một phương thức hoạt động nếu được gọi từ một bối cảnh khác nhau?
Fabian Schmengler

Tôi đã cập nhật câu hỏi ban đầu của mình để hiển thị phương thức sendStatusMail. Nếu bạn không phiền giúp đỡ thêm. Cảm ơn bạn.
thismethod

Bất kỳ cơ hội nào bạn có thể cho tôi ý kiến ​​của bạn về phương thức sendStatusMail ($ sản phẩm) của tôi?
thismethod

Tôi không thể phát hiện ra bất kỳ lỗi nào ở đó, xin lỗi
Fabian Schmengler

0

nhà cung cấp / 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;
}

Chúng ta hãy xem việc tiết kiệm thực thể sản phẩm.

-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

Đây là mã của hàm commit:

/**
 * 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;
}

Chúng ta hãy xem xét ví dụ của chúng tôi chặt chẽ hơn.

  1. $this->getConnection()->commit();đưa các giá trị vào DB cho cấp 1 của chúng tôi (đó là Stock). Nếu một cái gì đó xấu xảy ra ở đây, ngoại lệ sẽ được ném và tất cả các thay đổi sẽ được khôi phục.

  2. Sau đó, nó đi đến quá trình gọi lại. Vì chúng tôi hiện đang ở cấp 1, sẽ không có cuộc gọi lại nào được gọi. Và chúng tôi đang chuyển ra từ sự kiện catalog_product_after_save để cam kết thay đổi sản phẩm (mức 0).

  3. $this->getConnection()->commit();đặt các giá trị vào DB cho cấp 0 của chúng tôi (chính là Sản phẩm). Nếu một cái gì đó xấu xảy ra ở đây, ngoại lệ cũng sẽ được ném và tất cả các thay đổi cũng sẽ được khôi phục.

  4. Sau đó, chúng tôi đang chuyển sang thực hiện cuộc gọi lại. Bây giờ chúng tôi đang ở mức 0 và các cuộc gọi lại sẽ được chạy. Bất cứ điều gì bạn xấu bên trong call_user_func($callback);sẽ được bắt kịp và chỉ cần đăng nhập. Sẽ không có gì được khôi phục nếu gọi lại gây ra ngoại lệ

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.