Différence entre catalog_product_save_after et catalog_product_save_commit_after?


8

Quelqu'un peut-il expliquer la différence entre ces événements. Juste rapide et sale s'il vous plaît. Je vous remercie.

J'ai une méthode Observer comme ça:

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

Il ne s'agit pas de sendStatusMail()

Je suis accro à l'événement:

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

Dois-je utiliser: catalog_product_save_commit_after

OBJECTIF:

Faites envoyer un e-mail après la désactivation du produit.

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

vous devez utiliser l'événement <catalog_product_status_update>
Nickool

Est-ce la raison pour laquelle il ne tire pas? Vous utilisez simplement le mauvais événement? @Nickool
thismethod

Réponses:


14

L'enregistrement se produit dans une transaction MySQL et l' save_afterévénement est déclenché avant que la transaction ne soit validée, afin que vous puissiez effectuer des mises à jour supplémentaires dans la base de données au sein de la même transaction.

L' save_commit_afterévénement est déclenché après la validation de la transaction, c'est-à-dire lorsque les modifications ont été écrites dans la base de données.

De plus, le save_commit_after, la _hasDataChangespropriété a déjà été réinitialisée false, donc votre chèque ne fonctionnera pas. En revanche, s'il n'y avait pas de changements, les deux événements ne seraient même pas déclenchés, car Mage_Core_Model_Abstract :: save () ne fait rien s'il n'y avait pas de changements de données:

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

Cela étant dit, je ne vois pas pourquoi votre code ne devrait pas fonctionner.


Merci pour la réponse. Lorsque j'ajoute un Mage :: log () à la place de sendStatusMail (), j'obtiens le message de journal correctement. Mais ce n'est pas l'envoi de courriels. Je me suis assuré que "Désactiver les communications par e-mail" est défini sur NON et que mon adresse e-mail se trouve dans mes e-mails personnalisés> adresses e-mail du magasin. D'autres idées pourquoi cela ne fonctionne pas? @fschmengler
thismethod

Sans connaître votre méthode sendStatusMail, non. C'est probablement une question pour une autre question. Ou la même méthode fonctionne-t-elle si elle est appelée à partir d'un contexte différent?
Fabian Schmengler du

J'ai mis à jour ma question d'origine pour montrer la méthode sendStatusMail. Si cela ne vous dérange pas de vous aider davantage. Je vous remercie.
thismethod

Avez-vous des chances de me donner votre avis sur ma méthode sendStatusMail ($ product)?
thismethod

Je ne trouve aucune erreur là-bas, désolé
Fabian Schmengler

0

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

Jetons un coup d'œil à la sauvegarde de l'entité produit.

-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

Voici le code de la fonction 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;
}

Examinons notre exemple de plus près.

  1. $this->getConnection()->commit();mettre des valeurs dans DB pour notre 1er niveau (c'est Stock). Si quelque chose de mauvais se produit ici, une exception sera levée et toutes les modifications seront annulées.

  2. Ensuite, il va traiter les rappels. Comme nous sommes actuellement au 1er niveau, aucun rappel ne sera appelé. Et nous quittons l'événement catalog_product_after_save pour valider les modifications de produit (niveau 0).

  3. $this->getConnection()->commit();mettre des valeurs dans DB pour notre niveau 0 (c'est le produit lui-même). Si quelque chose de mauvais se produit ici, une exception sera également levée et toutes les modifications seront également annulées.

  4. Ensuite, nous passons à l'exécution des rappels. Nous sommes maintenant au niveau 0 et les rappels seront exécutés. Tout ce que vous avez de mal à l'intérieur call_user_func($callback);sera rattrapé et simplement enregistré. Rien ne sera annulé si le rappel provoque une exception

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.