Bagaimana mencegah data model disimpan menggunakan _save_before acara


8

Saya telah membuat model yang memiliki tabel database sendiri. Untuk penyesuaian saya perlu memicu save_beforeacara model ini.

Jika satu nilai bidang tidak cocok, maka data tidak boleh disimpan.

Target utama saya adalah mencegah penyimpanan data menggunakan acara "sebelum menyimpan"

Kode config.xml saya:

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


}
}

Jawaban:


17

Jika Anda melihat metode ini Mage_Core_Model_Abstract::save, Anda melihat blok kode ini:

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

Pada _beforeSave()metode di baris kedua, save_beforeacara dikirim. Oleh karena itu, Anda harus bisa melemparkan pengecualian dalam kode pengamat Anda. Ini harus ditangkap oleh blok uji coba di atas dan harus mencegah model untuk menyimpan.

Kemungkinan lain adalah _dataSaveAllowedlapangan. Anda dapat mengaturnya ke false dalam kode pengamat Anda. Ini akan mencegah model untuk menyimpan. Dan bidang ini dirancang khusus untuk tujuan ini seperti yang diungkapkan oleh dokumen 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 untuk mengungkapkan $_dataSaveAllowedproperti.
Rajeev K Tomy

simon, bisa tolong periksa p @ programmer_rkt jawab, apakah logika yang baik?
Amit Bera

upvote for u ...
Amit Bera

1
@AmitBera Rasanya agak hacky apa yang dia lakukan dan saya tidak benar-benar mengerti intinya ... Lihat komentar saya.
Simon

1
Ah maaf, saya melewatkan bidang itu protected. Saya pikir Anda dapat melakukan sesuatu seperti $observer->getDataObject()->setDataSaveAllowed(false), tetapi tidak ada setter masing-masing. Karenanya, Anda hanya dapat menggunakan pendekatan ini dengan model khusus tempat Anda dapat menambahkan setter untuk bidang tersebut. Untuk Magento atau model lain yang tidak Anda kontrol, gunakan pendekatan pengecualian.
Simon

2

Jika Anda perlu mencegah metode penyimpanan untuk mengeksekusi untuk model inti (yaitu Katalog / Produk), Anda dapat menggunakan refleksi untuk menetapkan "$ _dataSaveAllowed" menjadi 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

Anda harus mencoba jawaban @Simon terlebih dahulu. Tetapi jika Anda masih harus menyimpan untuk kedua kondisi, maka Anda dapat menggunakan cocept ini

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

Apa metode ini adalah, pertama-tama akan mengumpulkan data yang sesuai dengan entitas yang akan menyimpan dan kemudian mengatur data saat ini dengan nilai itu. Hasil ini menyimpan nilai sebelumnya sendiri ke dalam database. Jika tidak ada id entitas sekarang, itu berarti entitas baru. Jadi simpan nilai null untuk bidang itu

EDIT

Teman saya Simon dan AmitBera bingung pada bagian ini

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

Jadi akan lebih baik untuk menjelaskan bagian ini sedikit. Misalkan tabel memiliki dua fiels field_onedan field_two. Dalam hal itu, untuk entitas baru (berarti ini tidak memiliki entri dalam database), kita dapat mengatur nilai-nilai seperti ini.

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

Ini akan menghapus nilai yang berlalu dan menetapkan nilai nol. Jadi selama tindakan simpanan, nilai kosong ini akan disimpan dalam database.

Anggaplah bahwa saya mencoba untuk menyampaikan dan tolong jangan menilai berdasarkan kode demo yang saya berikan :)


Bisakah Anda menjelaskannya sedikit lebih jauh? Saya tidak begitu mengerti maksudnya. Ide dasarnya adalah bahwa ketika Anda mengatur data ke nol, tidak ada yang akan disimpan?
Simon

1
ini adalah before_savetindakan. Sarana savedan aftersavetindakan harus dilakukan. Jadi entitas yang diedit mungkin sudah ada dalam database atau yang baru. Jika entitas yang diedit memiliki entri dalam database, kita akan mendapatkan nilai-nilai itu dan mengatur nilai-nilai itu alih-alih nilai-nilai yang berubah saat ini dimiliki oleh entitas / objek. jadi ketika tindakan save terjadi, nilai yang ditetapkan sekarang adalah nilai sebelumnya itu sendiri. Ini tidak membuat pembaruan nilai tabel. Berarti nilai sebelumnya bisa disimpan.
Rajeev K Tomy

untuk entitas baru, berarti yang tidak memiliki entri dalam database, alih-alih menggunakan nilai awal yang saat ini dimiliki oleh entitas itu, kami menetapkan nilai null. Ini akan membuat entri baru dalam database dengan semua bidang memiliki nilai nol di dalamnya. jika setData(null)tidak berhasil, saya kira setData(array())mungkin berfungsi (null array). Ini hanya logika
Rajeev K Tomy

@Simon: apakah Anda mengerti maksud saya?
Rajeev K Tomy

2
Ya, benar, terima kasih. Terasa sedikit berantakan. Dan itu bisa menyelamatkan entitas dummy yang bukan perilaku yang diinginkan.
Simon

0

Ini mungkin memengaruhi lebih dari sekadar objek pelanggan yang Anda coba cegah untuk tidak ditabung, tetapi Anda bisa melakukan ini di pengamat Anda untuk mencegah penyimpanan dari diterapkan dalam basis data.

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

Pengecualian yang dilemparkan saja tidak akan melakukannya, jadi Anda harus mencoba untuk mengembalikan transaksi dengan InnoDB. Namun, mungkin ada lebih dari sekedar akun pelanggan ini yang dimodifikasi / dibuat dalam transaksi itu, jadi gunakan ini dengan hati-hati.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.