So verhindern Sie das Speichern von Modelldaten mithilfe des Ereignisses _save_before

8

Ich habe ein Modell erstellt, das eine eigene Datenbanktabelle hat. Für eine Anpassung muss ich ein save_beforeEreignis dieses Modells auslösen .

Wenn ein Feldwert nicht übereinstimmt, sollten die Daten nicht gespeichert werden.

Mein Hauptziel ist das Verhindern des Speicherns von Daten mithilfe des Ereignisses "vor dem Speichern"

Mein config.xml-Code:

<?xml version="1.0" ?>
<config>
    <modules>
        <Amit_Custommodule>
            <version>1.0.0</version>
        </Amit_Custommodule>
    </modules>
    <global>
        <models>
            <custommodule>
                <class>Amit_Custommodule_Model</class>
                <resourceModel>custommodule_resource</resourceModel>
            </custommodule>
            <custommodule_resource>
                <class>Amit_Custommodule_Model_Resource</class>
                <entities>
                    <custommodule>
                        <table>custommodule</table>
                    </custommodule>
                </entities>
            </custommodule_resource>
        </models>
        <resources>
            <custommodule_setup>
                <setup>
                    <module>Amit_Custommodule</module>
                </setup>
                <connection>
                    <use>core_setup</use>
                </connection>
            </custommodule_setup>
            <custommoule_read>
                <connection>
                    <use>core_read</use>
                </connection>
            </custommoule_read>
            <custommodule_write>
                <connection>
                    <use>core_write</use>
                </connection>
            </custommodule_write>
        </resources>
        <events>
            <custommodule_save_before>
                <observers>
                    <custommodule>
                        <type>singleton</type>
                        <class>custommodule/observer</class>
                        <method>customerSaveAfter</method>
                    </custommodule>
                </observers>
            </custommodule_save_before>
    </global>


</config>

Observer.php

<?php
class Amit_Custommodule_Model_Observer
{
public function customerSaveAfter($observer){

if($observer->getEvent()->getMyfield()==MatchWithMyLogic){
}
else
{
/*  i want prevent data base if my business logic is not match here */
}


}
}
Amit Bera
quelle

Antworten:

17

Wenn Sie sich die Methode ansehen Mage_Core_Model_Abstract::save, sehen Sie diesen Codeblock:

try {
    $this->_beforeSave();
    if ($this->_dataSaveAllowed) {
        $this->_getResource()->save($this);
        $this->_afterSave();
    }
    $this->_getResource()->addCommitCallback(array($this, 'afterCommitCallback'))
        ->commit();
    $this->_hasDataChanges = false;
    $dataCommited = true;
} catch (Exception $e) {
    $this->_getResource()->rollBack();
    $this->_hasDataChanges = true;
    throw $e;
}

Bei der _beforeSave()Methode in der zweiten Zeile wird das save_beforeEreignis ausgelöst. Daher sollten Sie nur eine Ausnahme in Ihrem Beobachtercode auslösen können. Dies sollte vom obigen Try-Catch-Block abgefangen werden und das Speichern des Modells verhindern.

Eine andere Möglichkeit ist das _dataSaveAllowedFeld. Sie können es in Ihrem Beobachtercode auf false setzen. Dadurch wird verhindert, dass das Modell gespeichert wird. Und dieses Feld ist genau für diesen Zweck konzipiert, wie das PHP-Dokument zeigt:

/**
 * Flag which can stop data saving after before save
 * Can be used for next sequence: we check data in _beforeSave, if data are
 * not valid - we can set this flag to false value and save process will be stopped
 *
 * @var bool
 */
protected $_dataSaveAllowed = true;
Simon
quelle
4
+1 für das Aufdecken von $_dataSaveAllowedEigentum.
Rajeev K Tomy
Simon, kannst du bitte die Antwort von p @ programmer_rkt überprüfen? Ist das eine gute Logik?
Amit Bera
upvote for u ...
Amit Bera
1
@AmitBera Fühlt sich ein bisschen hacky an, was er tut und ich verstehe den Punkt nicht wirklich ... Siehe meinen Kommentar.
Simon
1
Tut mir leid, ich habe vermisst, dass das Feld ist protected. Ich dachte, dass Sie so etwas tun können $observer->getDataObject()->setDataSaveAllowed(false), aber es gibt keinen entsprechenden Setter. Daher können Sie diesen Ansatz nur mit einem benutzerdefinierten Modell verwenden, bei dem Sie einen Setter für das Feld hinzufügen können. Verwenden Sie für Magento oder andere Modelle, die Sie nicht steuern, den Ausnahmeansatz.
Simon
2

Falls Sie verhindern müssen, dass die Speichermethode für ein Kernmodell (z. B. Katalog / Produkt) ausgeführt wird, können Sie mithilfe von Reflection "$ _dataSaveAllowed" auf false setzen:

public function catalogProductSaveBefore($observer)
{
    try {
        $product = $observer->getProduct();

        $reflectionClass = new ReflectionClass('Mage_Catalog_Model_Product');
        $reflectionProperty = $reflectionClass->getProperty('_dataSaveAllowed');
        $reflectionProperty->setAccessible(true);
        $reflectionProperty->setValue($product, false);
    } catch (Exception $e) {
            Mage::log($e->getMessage());
    }

    return $this;
}
José Romero
quelle
1

Sie sollten zuerst versuchen, @ Simon zu antworten. Wenn Sie jedoch in beiden Fällen noch speichern müssen, können Sie dieses Konzept verwenden

<?php
class Amit_Custommodule_Model_Observer
{
    public function customerSaveAfter($observer)
    {

        if ($observer->getEvent()->getMyfield() == MatchWithMyLogic) {
            //do some other works
            //save data normally
        } else {
            //defines your modules model
            $model = Mage::getModel('model_alias/entity');
            //get entity id that is trying to save if any
            $id = (int)$observer->getEvent()->getEntityId();
            if ($id >= 0 ) {
                //load the correspondign model and retrieve data
                $data = $model->load($id)->getData();

                //set this value to the current object that is trying to save
                $observer->getEvent()->setData($data); 
            } else {
                //set null value for all fields for new entity
                $observer->getEvent()->setData(null);
            }
        }
    }
}

Bei dieser Methode werden zunächst Daten erfasst, die der zu speichernden Entität entsprechen, und anschließend die aktuellen Daten mit diesem Wert festgelegt. Dies führt dazu, dass der vorherige Wert selbst in der Datenbank gespeichert wird. Wenn keine Entitäts-ID vorhanden ist, bedeutet dies, dass es sich um eine neue Entität handelt. Speichern Sie also Nullwerte für dieses Feld

BEARBEITEN

Meine Freunde Simon und AmitBera waren in diesem Punkt verwirrt

else {
        //set null value for all fields for new entity
        $observer->getEvent()->setData(null);
}

Es wäre also gut, diesen Teil ein wenig zu erklären. Angenommen, die Tabelle hat zwei Felder field_oneund field_two. In diesem Fall können wir für eine neue Entität (dh dies hat keinen Eintrag in der Datenbank) diese Werte wie folgt festlegen.

 $observer->getEvent()->setEntityOne('');
  $observer->getEvent()->setEntityTwo('');

Dadurch wird der übergebene Wert gelöscht und der Nullwert festgelegt. Während der Speicheraktion werden diese leeren Werte in der Datenbank gespeichert.

Nehmen Sie an, dass ich versuche zu vermitteln und beurteilen Sie bitte nicht anhand des von mir bereitgestellten Demo-Codes :)

Rajeev K Tomy
quelle
Könnten Sie es etwas näher erläutern? Ich verstehe den Punkt nicht wirklich. Die Grundidee ist, dass nichts gespeichert wird, wenn Sie die Daten auf null setzen?
Simon
1
Das ist before_saveAktion. Mittel saveund aftersaveHandlungen müssen stattfinden. Die bearbeitete Entität ist möglicherweise bereits in der Datenbank vorhanden oder eine neue. Wenn die bearbeitete Entität einen Eintrag in der Datenbank hat, erhalten wir diese Werte und legen diese Werte anstelle der geänderten Werte fest, die derzeit von der Entität / dem Objekt gehalten werden. Wenn also eine Speicheraktion stattfindet, ist der jetzt festgelegte Wert der vorherige Wert. Dies führt keine Aktualisierung des Tabellenwerts durch. Bedeutet, dass vorherige Werte gespeichert werden.
Rajeev K Tomy
Für neue Entitäten bedeutet dies, dass diese keinen Eintrag in der Datenbank haben. Anstatt Anfangswerte zu verwenden, die derzeit von dieser Entität gehalten werden, setzen wir Nullwerte. Dadurch wird ein neuer Eintrag in der Datenbank erstellt, in dem alle Felder den Wert Null enthalten. Wenn es setData(null)nicht funktioniert hat, setData(array())kann es funktionieren (Null-Array). Es ist nur eine Logik
Rajeev K Tomy
@ Simon: Hast du meinen Standpunkt verstanden?
Rajeev K Tomy
2
Ja, danke. Fühlt sich ein bisschen hackig an. Und es kann eine Dummy-Entität speichern, die nicht das gewünschte Verhalten ist.
Simon
0

Dies kann mehr als nur das Kundenobjekt betreffen, dessen Speicherung Sie verhindern möchten . Sie können dies jedoch in Ihrem Beobachter tun, um zu verhindern, dass die Speicherung in der Datenbank angewendet wird.

$customer->getResource()->rollBack();
Mage::throwException('Invalid customer account information');

Die ausgelöste Ausnahme allein reicht nicht aus. Sie müssen daher versuchen, die Transaktion mit InnoDB zurückzusetzen. Möglicherweise wird in dieser Transaktion jedoch mehr als nur dieses Kundenkonto geändert / erstellt. Verwenden Sie dieses Konto daher mit Vorsicht.

Tyler V.
quelle