Как предотвратить сохранение данных модели с помощью события _save_before

8

Я создал модель, которая имеет свою собственную таблицу базы данных. Для настройки мне нужно вызвать save_beforeсобытие этой модели.

Если одно значение поля не соответствует, то данные не должны быть сохранены.

Моя главная цель - предотвратить сохранение данных с помощью события «before save»

Мой код 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 */
}


}
}
Амит Бера
источник

Ответы:

17

Если вы посмотрите на метод Mage_Core_Model_Abstract::save, вы увидите этот блок кода:

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

Во _beforeSave()втором методе save_beforeсобытие отправляется. Следовательно, вы должны иметь возможность просто добавить исключение в ваш код наблюдателя. Это должно быть перехвачено блоком try-catch выше и должно препятствовать сохранению модели.

Другая возможность - это _dataSaveAllowedполе. Вы можете установить его в false в своем коде наблюдателя. Это предотвратит сохранение модели. И это поле специально разработано для этой цели, как показывает документ 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 за раскрытие $_dataSaveAllowedсобственности.
Раджив К Томи
Саймон, можешь проверить ответ p @ programmer_rkt, хорошая логика?
Амит Бера
upvote для тебя ...
Амит Бера
1
@AmitBera Чувствует себя немного хакерским, что он делает, и я не совсем понимаю ... Смотрите мой комментарий.
Саймон
1
Ах, прости, я пропустил, что поле есть protected. Я думал, что вы можете сделать что-то вроде $observer->getDataObject()->setDataSaveAllowed(false), но нет соответствующего сеттера. Следовательно, вы можете использовать этот подход только с пользовательской моделью, где вы можете добавить установщик для поля. Для Magento или других моделей, которые вы не контролируете, используйте подход исключения.
Саймон
2

В случае, если вам нужно запретить выполнение метода save для базовой модели (например, Catalog / Product), вы можете использовать отражение, чтобы установить для "$ _dataSaveAllowed" значение 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

Вы должны сначала попробовать ответ @Simon. Но если вам все еще нужно сохранить данные в обоих условиях, вы можете использовать эту концепцию

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

Этот метод сначала собирает данные, соответствующие объекту, который будет сохранен, а затем устанавливает текущие данные с этим значением. Это приводит к сохранению самого предыдущего значения в базе данных. Если идентификатор сущности отсутствует, это означает, что это новая сущность. Так что сохраните нулевые значения для этого поля

РЕДАКТИРОВАТЬ

Мои друзья Саймон и АмитБера запутались в этой части

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

Так что было бы хорошо немного объяснить эту часть. Предположим, что в таблице есть два поля field_oneи field_two. В этом случае для новой сущности (означает, что у нее нет записи в базе данных), мы можем установить эти значения следующим образом.

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

Это удалит переданное значение и установит нулевое значение. Таким образом, во время действия сохранения эти пустые значения будут сохранены в базе данных.

Возьмите идею, что я пытаюсь передать, и, пожалуйста, не судите по предоставленному мной демонстрационному коду :)

Раджив К Томи
источник
Не могли бы вы объяснить это немного дальше? Я не совсем понимаю суть. Основная идея заключается в том, что когда вы устанавливаете данные на ноль, ничего не будет сохранено?
Саймон
1
это before_saveдействие. Средства saveи aftersaveдействия должны иметь место. Таким образом, отредактированный объект может быть уже существующим в базе данных или новым. Если отредактированная сущность имеет запись в базе данных, мы получим эти значения и установим эти значения вместо измененных значений, которые в данный момент хранятся в сущности / объекте. поэтому, когда происходит действие сохранения, значение, установленное сейчас, является самим предыдущим значением. Это не делает обновление значения таблицы. Значит предыдущие значения сохраняются.
Раджив К Томи
для новых сущностей означает, что они не имеют записи в базе данных, вместо использования начальных значений, которые в данный момент хранятся в этой сущности, мы устанавливаем нулевые значения. Это создаст новую запись в базе данных со всеми полями, имеющими нулевое значение. если setData(null)не работает, я думаю, setData(array())может работать (нулевой массив). Это просто логика
Rajeev K Tomy
@ Симон: ты понял мою точку зрения?
Раджив К Томи
2
Да, спасибо. Чувствует себя немного хакером. И это может сохранить фиктивную сущность, которая не является желаемым поведением.
Саймон
0

Это может повлиять не только на объект клиента, который вы пытаетесь запретить сохранение , но вы можете сделать это в обозревателе, чтобы предотвратить применение сохранения в базе данных.

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

Одно только выброшенное исключение не сделает этого, поэтому вы должны попытаться откатить транзакцию с InnoDB. Однако в этой транзакции может быть что-то большее, чем просто изменение / создание этой учетной записи клиента, поэтому используйте это с осторожностью.

Тайлер В.
источник