Como evitar que os dados de um modelo sejam salvos usando o evento _save_before

8

Eu criei um modelo que possui sua própria tabela de banco de dados. Para uma personalização, eu preciso acionar um save_beforeevento desse modelo.

Se um valor de campo não corresponder, os dados não deverão ser salvos.

Meu principal objetivo é impedir que os dados sejam salvos usando o evento "antes de salvar"

Meu código 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 */
}


}
}
Amit Bera
fonte

Respostas:

17

Se você der uma olhada no método Mage_Core_Model_Abstract::save, verá este bloco de código:

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

No _beforeSave()método na segunda linha, o save_beforeevento é despachado. Portanto, você deve ser capaz de lançar uma exceção no seu código de observador. Isso deve ser capturado pelo bloco try-catch-block acima e deve impedir que o modelo seja salvo.

Outra possibilidade é o _dataSaveAllowedcampo. Você pode configurá-lo como false no seu código de observador. Isso impedirá que o modelo seja salvo. E esse campo foi projetado exatamente para esse fim, conforme o documento PHP revela:

/**
 * 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
fonte
4
+1 por revelar $_dataSaveAllowedpropriedade.
Rajeev K Tomy 02/09
Simon, você pode verificar a resposta de p @ programmer_rkt, é uma boa lógica?
Amit Bera
upvote para u ...
Amit Bera
11
@AmitBera Parece um pouco hacky o que ele faz e eu realmente não entendo o ponto ... Veja meu comentário.
Simon
11
Desculpe, eu perdi o campo protected. Eu pensei que você pode fazer algo parecido $observer->getDataObject()->setDataSaveAllowed(false), mas não há nenhum levantador respectivo. Portanto, você só pode usar essa abordagem com um modelo personalizado no qual você pode adicionar um setter para o campo. Para Magento ou outros modelos que você não controla, use a abordagem de exceção.
Simon
2

Caso você precise impedir que o método save seja executado para um modelo principal (por exemplo, Catálogo / Produto), você pode usar a reflexão para definir "$ _dataSaveAllowed" como 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;
}
José Romero
fonte
1

Você deve tentar a resposta do @Simon primeiro. Mas se você ainda precisar economizar nas duas condições, poderá usar este cocept

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

O que esse método faz é: ele primeiro coletará dados correspondentes à entidade que será salva e, em seguida, definirá os dados atuais com esse valor. Isso resulta em salvar o próprio valor anterior no banco de dados. Se não houver um ID de entidade presente, isso significa que é uma nova entidade. Portanto, salve valores nulos para esse campo

EDITAR

Meus amigos Simon e AmitBera ficaram confusos com essa parte

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

Portanto, seria bom explicar um pouco essa parte. Suponha que a tabela tenha dois campos field_onee field_two. Nesse caso, para uma nova entidade (significa que isso não tem entrada no banco de dados), podemos definir esses valores dessa maneira.

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

Isso apagará o valor que passou e definirá o valor nulo. Portanto, durante a ação de salvar, esses valores vazios serão armazenados no banco de dados.

Tome a idéia de que estou tentando transmitir e não julgue com base no código de demonstração que forneço :)

Rajeev K Tomy
fonte
Você poderia explicar um pouco mais? Eu realmente não entendo o ponto. A ideia base é que, quando você define os dados como nulos, nada será salvo?
Simon
11
isso é before_saveação. Meios savee aftersaveações devem ocorrer. Portanto, a entidade editada pode já existir uma no banco de dados ou uma nova. Se a entidade editada tiver uma entrada no banco de dados, obteremos esses valores e os definiremos em vez dos valores alterados atualmente mantidos pela entidade / objeto. portanto, quando a ação de salvar ocorre, o valor definido agora é o próprio valor anterior. Isso não faz a atualização do valor da tabela. Significa que os valores anteriores são salvos.
Rajeev K Tomy
para novas entidades, significa que elas não têm entrada no banco de dados. Em vez de usar valores iniciais atualmente retidos por essa entidade, definimos valores nulos. Isso criará uma nova entrada no banco de dados com todos os campos com valor nulo. se setData(null)não funcionou, acho que setData(array())pode funcionar (matriz nula). É apenas uma lógica
Rajeev K Tomy 02/02
@ Simon: você entendeu meu ponto?
Rajeev K Tomy
2
Sim, obrigado. Parece um pouco hacky. E isso pode salvar uma entidade fictícia que não é o comportamento desejado.
Simon
0

Isso pode afetar mais do que apenas o objeto do cliente que você está tentando impedir de salvar , mas você pode fazer isso no seu observador para impedir que a gravação seja aplicada no banco de dados.

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

A exceção lançada por si só não fará isso; portanto, você deve tentar reverter a transação com o InnoDB. No entanto, pode haver mais do que apenas essa conta de cliente sendo modificada / criada nessa transação, portanto, use isso com cuidado.

Tyler V.
fonte