Cách ngăn dữ liệu mô hình lưu bằng cách sử dụng sự kiện _save_b Before


8

Tôi đã tạo một mô hình có bảng cơ sở dữ liệu riêng. Để tùy chỉnh tôi cần kích hoạt save_beforesự kiện của mô hình này.

Nếu một giá trị trường không khớp, thì dữ liệu sẽ không được lưu.

Mục tiêu chính của tôi là ngăn chặn lưu dữ liệu bằng cách sử dụng sự kiện "trước khi lưu"

Mã cấu hình của tôi:

<?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>

Quan sát.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 */
}


}
}

Câu trả lời:


17

Nếu bạn đã xem phương thức này Mage_Core_Model_Abstract::save, bạn sẽ thấy khối mã này:

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

Trong _beforeSave()phương thức trong dòng thứ hai, save_beforesự kiện được gửi đi. Do đó, bạn sẽ có thể ném một ngoại lệ vào mã người quan sát của bạn. Điều này nên được bắt bởi khối thử bắt ở trên và nên ngăn mô hình lưu lại.

Một khả năng khác là _dataSaveAllowedlĩnh vực. Bạn có thể đặt nó thành false trong mã người quan sát của bạn. Điều này sẽ ngăn chặn mô hình để tiết kiệm. Và trường này được thiết kế chính xác cho mục đích này khi tài liệu PHP tiết lộ:

/**
 * 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 để tiết lộ $_dataSaveAllowedtài sản.
Rajeev K Tomy

simon, bạn có thể vui lòng kiểm tra câu trả lời p @ lập trình_rkt không, logic có tốt không?
Amit Bera

upvote cho bạn ...
Amit Bera

1
@AmitBera Cảm thấy một chút hacky những gì anh ấy làm và tôi thực sự không nhận được điểm ... Xem nhận xét của tôi.
Simon

1
Ah xin lỗi, tôi đã bỏ lỡ rằng lĩnh vực này protected. Tôi nghĩ rằng bạn có thể làm một cái gì đó như thế $observer->getDataObject()->setDataSaveAllowed(false), nhưng không có setter tương ứng. Do đó, bạn chỉ có thể sử dụng phương pháp này với một mô hình tùy chỉnh nơi bạn có thể thêm một trình thiết lập cho trường. Đối với Magento hoặc các mô hình khác mà bạn không kiểm soát, hãy sử dụng phương pháp ngoại lệ.
Simon

2

Trong trường hợp bạn cần ngăn phương thức lưu để thực thi cho mô hình lõi (ví dụ: Danh mục / Sản phẩm), bạn có thể sử dụng phản chiếu để đặt "$ _dataSave ALLowed" thành 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

Bạn nên thử trả lời @Simon trước. Nhưng nếu bạn vẫn cần phải tiết kiệm trong cả hai điều kiện, thì bạn có thể sử dụng cocept này

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

Phương thức này làm là gì, trước tiên nó sẽ thu thập dữ liệu tương ứng với thực thể sẽ lưu và sau đó đặt dữ liệu hiện tại với giá trị đó. Điều này dẫn đến việc lưu chính giá trị trước đó vào cơ sở dữ liệu. Nếu không có id thực thể, điều đó có nghĩa là thực thể mới. Vì vậy, lưu giá trị null cho trường đó

BIÊN TẬP

Bạn bè của tôi Simon và AmitBera đã nhầm lẫn về phần này

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

Vì vậy, nó sẽ là tốt để giải thích phần này một chút. Giả sử bảng có hai fiels field_onefield_two. Trong trường hợp đó, đối với một thực thể mới (có nghĩa là điều này không có mục trong cơ sở dữ liệu), chúng ta có thể đặt các giá trị như thế này.

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

Điều này sẽ xóa giá trị đã vượt qua và đặt giá trị null. Vì vậy, trong quá trình lưu hành động, giá trị trống này sẽ được lưu trữ trong cơ sở dữ liệu.

Hãy biết rằng tôi đang cố gắng truyền đạt và xin đừng phán xét trên cơ sở mã demo mà tôi đã cung cấp :)


Bạn có thể giải thích thêm một chút? Tôi không thực sự có được điểm. Ý tưởng cơ bản là khi bạn đặt dữ liệu thành null, sẽ không có gì được lưu?
Simon

1
đây là before_savehành động Phương tiện saveaftersavehành động phải diễn ra. Vì vậy, thực thể được chỉnh sửa có thể đã tồn tại một thực thể trong cơ sở dữ liệu hoặc một thực thể mới. Nếu thực thể được chỉnh sửa có một mục trong cơ sở dữ liệu, chúng ta sẽ nhận các giá trị đó và đặt các giá trị đó thay vì các giá trị thay đổi hiện đang được giữ bởi thực thể / đối tượng. vì vậy khi hành động lưu diễn ra, giá trị được đặt bây giờ là giá trị trước đó. Điều này làm cho không có cập nhật giá trị bảng. Có nghĩa là các giá trị trước đó được lưu.
Rajeev K Tomy

đối với các thực thể mới, có nghĩa là các thực thể không có mục nhập trong cơ sở dữ liệu, thay vì sử dụng các giá trị ban đầu hiện đang được giữ bởi thực thể đó, chúng tôi đặt các giá trị null. Điều này sẽ tạo một mục mới trong cơ sở dữ liệu với tất cả các trường có giá trị null trong đó. nếu không setData(null)hoạt động, tôi đoán setData(array())có thể làm việc (mảng null). Nó chỉ là một logic
Rajeev K Tomy

@Simon: bạn đã nhận được quan điểm của tôi?
Rajeev K Tomy

2
Vâng, tôi đã làm, cảm ơn. Cảm thấy một chút hacky. Và nó có thể cứu một thực thể giả không phải là hành vi mong muốn.
Simon

0

Điều này có thể ảnh hưởng nhiều hơn đến đối tượng khách hàng mà bạn đang cố gắng ngăn chặn , nhưng bạn có thể làm điều này trong trình quan sát của mình để ngăn việc lưu được áp dụng trong cơ sở dữ liệu.

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

Ngoại lệ bị ném một mình sẽ không làm điều đó, vì vậy bạn phải cố gắng hoàn nguyên giao dịch với InnoDB. Tuy nhiên, có thể có nhiều hơn chỉ tài khoản khách hàng này được sửa đổi / tạo trong giao dịch đó, vì vậy hãy thận trọng khi sử dụng tài khoản này.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.