_save_beforeイベントを使用してモデルデータを保存しないようにする方法


8

独自のデータベーステーブルを持つモデルを作成しました。カスタマイズするにsave_beforeは、このモデルのイベントをトリガーする必要があります。

1つのフィールド値が一致しない場合、データは保存されません。

私の主な目標は、「保存前」イベントを使用したデータの保存を防ぐことです

私の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()2行目のメソッドでは、save_beforeイベントが送出されています。したがって、オブザーバーコードで例外をスローすることができるはずです。これは上記のtry-catch-blockによってキャッチされ、モデルが保存されないようにする必要があります。

別の可能性は_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
$_dataSaveAllowedプロパティを明らかにするための+1 。
Rajeev K Tomy 14

サイモン、p @ programmer_rktの答えを確認してください、論理は良いですか?
アミットベラ

uへの賛成投票
Amit Bera

1
@AmitBeraは彼が何をしているのか少しハックしているように感じます、そして私は本当にポイントを獲得しません...私のコメントを見てください
Simon

1
申し訳ありませんが、フィールドが欠落していますprotected。あなたはのようなことができると思い$observer->getDataObject()->setDataSaveAllowed(false)ましたが、それぞれのセッターはありません。したがって、このアプローチは、フィールドのセッターを追加できるカスタムモデルでのみ使用できます。Magentoまたは管理していない他のモデルの場合は、例外アプローチを使用します。
Simon

2

コアモデル(つまり、カタログ/製品)に対してsaveメソッドが実行されないようにする必要がある場合は、リフレクションを使用して "$ _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);
            }
        }
    }
}

この方法では、まず保存するエンティティに対応するデータを収集し、現在のデータにその値を設定します。これにより、以前の値自体がデータベースに保存されます。エンティティIDがない場合、それは新しいエンティティを意味します。そのフィールドのnull値を保存します

編集

友達のサイモンとアミットベラはこの部分で混乱しました

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

したがって、この部分を少し説明するとよいでしょう。テーブルに2つのフィールドfield_oneとがあるとしfield_twoます。その場合、新しいエンティティ(データベースにエントリがないことを意味します)の場合、これらの値を次のように設定できます。

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

これにより、渡された値が消去され、null値が設定されます。したがって、保存アクション中に、この空の値はデータベースに格納されます。

私が伝えようとしていることを考えてください。私が提供したデモコードに基づいて判断しないでください:)


もう少し詳しく説明してもらえますか?要点はわかりません。基本的な考え方は、データをnullに設定すると何も保存されないということです。
Simon

1
これはbefore_saveアクションです。手段saveaftersave行動が起こらなければならない。そのため、編集されたエンティティは、データベースにすでに存在しているか、新しいエンティティである可能性があります。編集されたエンティティがデータベースにエントリを持っている場合、その値を取得し、エンティティ/オブジェクトが現在保持している変更された値の代わりにそれらの値を設定します。そのため、保存アクションが発生すると、現在設定されている値は以前の値自体になります。これにより、テーブル値が更新されることはありません。以前の値が保存されることを意味します。
Rajeev K Tomy 14

新しいエンティティの場合、データベースにエントリがないため、現在そのエンティティが保持している初期値を使用する代わりに、null値を設定します。これにより、すべてのフィールドにnull値が含まれるデータベースに新しいエントリが作成されます。動作しsetData(null)なかったsetData(array())場合、動作する可能性があります(null配列)。その単なる論理
Rajeev Kトミー14

@サイモン:あなたは私のポイントを得ましたか?
Rajeev K Tomy 14

2
はい、ありがとうございます。少しハックを感じます。そして、それは望ましい動作ではないダミーエンティティを保存するかもしれません。
Simon

0

これは、保存を防止しようとしている顧客オブジェクト以外にも影響を与える可能性がありますが、オブザーバーでこれを行うと、保存がデータベースに適用されないようにすることができます。

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

スローされた例外だけではそれができないため、InnoDBでトランザクションをロールバックする必要があります。ただし、そのトランザクションで変更/作成されるのはこの顧客アカウントだけではない可能性があるため、注意して使用してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.