Come impedire il salvataggio dei dati di un modello utilizzando l'evento _save_before


8

Ho creato un modello che ha una propria tabella di database. Per una personalizzazione devo attivare l' save_beforeevento di questo modello.

Se un valore di campo non corrisponde, i dati non devono essere salvati.

Il mio obiettivo principale è impedire il salvataggio dei dati utilizzando l'evento "prima del salvataggio"

Il mio codice config.xml:

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


}
}

Risposte:


17

Se dai un'occhiata al metodo Mage_Core_Model_Abstract::save, vedi questo blocco di codice:

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

Nel _beforeSave()metodo nella seconda riga, l' save_beforeevento viene inviato. Quindi, dovresti essere in grado di generare un'eccezione nel tuo codice osservatore. Questo dovrebbe essere colto dal blocco try-catch sopra e dovrebbe impedire il salvataggio del modello.

Un'altra possibilità è il _dataSaveAllowedcampo. Puoi impostarlo su false nel tuo codice osservatore. Ciò impedirà il salvataggio del modello. E questo campo è progettato esattamente per questo scopo, come rivela il documento PHP:

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

4
+1 per rivelare la $_dataSaveAllowedproprietà.
Rajeev K Tomy,

simon, puoi per favore controllare la risposta di p @ programmer_rkt, è una buona logica?
Amit Bera

valuti per te ...
Amit Bera

1
@AmitBera Si sente un po 'confuso ciò che fa e non capisco davvero il punto ... Vedi il mio commento.
Simon,

1
Ah scusa, mi sono perso il campo protected. Ho pensato che puoi fare qualcosa del genere $observer->getDataObject()->setDataSaveAllowed(false), ma non esiste un setter corrispondente. Pertanto, è possibile utilizzare questo approccio solo con un modello personalizzato in cui è possibile aggiungere un setter per il campo. Per Magento o altri modelli che non controlli, utilizza l'approccio delle eccezioni.
Simon,

2

Nel caso in cui sia necessario impedire l'esecuzione del metodo di salvataggio per un modello principale (ad esempio Catalogo / Prodotto), è possibile utilizzare reflection per impostare "$ _dataSaveAllowed" su false:

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

1

Dovresti provare prima la risposta @Simon. Ma se hai ancora bisogno di salvare in entrambe le condizioni, puoi usare questo concetto

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

Ciò che fa questo metodo è, prima raccoglierà i dati corrispondenti all'entità che sta per salvare e quindi imposterà i dati correnti con quel valore. Ciò si traduce nel salvataggio del valore precedente stesso nel database. Se non è presente alcun ID entità, significa che si tratta di una nuova entità. Quindi salva valori null per quel campo

MODIFICARE

I miei amici Simon e AmitBera si sono confusi su questa parte

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

Quindi sarebbe bene spiegare un po 'questa parte. Supponiamo che la tabella abbia due campi field_onee field_two. In tal caso, per una nuova entità (significa che non ha alcuna voce nel database), possiamo impostare tali valori in questo modo.

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

Ciò cancellerà il valore passato e imposterà il valore null. Quindi durante l'azione di salvataggio, questi valori vuoti verranno archiviati nel database.

Pensa che sto cercando di comunicare e per favore non giudicare sulla base del codice demo che ho fornito :)


Potresti spiegarlo un po 'di più? Non capisco davvero il punto. L'idea di base è che quando si impostano i dati su null, nulla verrà salvato?
Simon,

1
questa è before_saveazione. Mezzi savee aftersaveazioni devono aver luogo. Pertanto, un'entità modificata potrebbe essere già esistente nel database o nuova. Se l'entità modificata ha una voce nel database, otterremo quei valori e imposteremo tali valori anziché i valori modificati che sono attualmente in possesso dell'entità / oggetto. quindi quando ha luogo l'azione di salvataggio, il valore impostato ora è il valore precedente stesso. Ciò non effettua alcun aggiornamento del valore della tabella. Significa che i valori precedenti vengono salvati.
Rajeev K Tomy,

per le nuove entità, significa che quelle non hanno alcuna voce nel database, invece di utilizzare i valori iniziali che sono attualmente in possesso di tale entità, impostiamo valori nulli. Ciò renderà una nuova voce nel database con tutto il campo che ha un valore null in esso. se non ha setData(null)funzionato, suppongo che setData(array())possa funzionare (null array). È solo una logica
Rajeev K Tomy,

@Simon: hai capito il mio punto?
Rajeev K Tomy,

2
Sì, grazie. Sembra un po 'confuso. E può salvare un'entità fittizia che non è il comportamento desiderato.
Simon,

0

Ciò può influire non solo sull'oggetto cliente che si sta tentando di impedire il salvataggio , ma è possibile farlo nel proprio osservatore per impedire che il salvataggio venga applicato nel database.

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

L'eccezione generata da sola non lo farà, quindi è necessario provare a ripristinare la transazione con InnoDB. Tuttavia, potrebbe esserci qualcosa di più di questo semplice account cliente che viene modificato / creato in quella transazione, quindi usalo con cautela.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.