Unregister quan sát sự kiện theo chương trình


7

Có ai biết nếu có thể hủy đăng ký một người quan sát sự kiện theo chương trình không? Tôi có một người quan sát newsletter_subscribe_save_aftercập nhật thuộc tính tùy chỉnh trong mô hình khách hàng nhưng khi lưu bản ghi khách hàng, nó sẽ kích hoạt customer_save_aftersự kiện được xác định trong Mage_All.xmlđó lưu lại trạng thái đăng ký bản tin dẫn đến một vòng lặp vô hạn sau đó gây ra lỗi đệ quy PHP làm tổ 100 lần.

Lý tưởng nhất là tôi muốn hủy đăng ký customer_save_aftersự kiện chỉ khi người quan sát của tôi kích hoạt.


Tôi không cần câu hỏi này, nhưng tôi thích nó. +1.
pspahn

Câu trả lời:


10

Bạn có thể cố gắng đánh dấu sự kiện của mình dispatchedvà trong lần thử thứ hai, nó không làm gì nếu nó đã được gửi đi. Ví dụ, giả sử phương thức của bạn được gọi updateCustomer().

public function updateCustomer($observer){
    if (Mage::registry('my_event_was_dispatched') == 1){//do nothing if the event was dispatched
        return $this;
    }
    //your code here
    Mage::register('my_event_was_dispatched', 1);//mark the event as dispatched.
}

Tên khóa đăng ký không quan trọng, chỉ cần đảm bảo bạn sử dụng cùng một tên trong cả hai trường hợp.


Làm việc như một giấc mơ. Một điều nhỏ, lợi nhuận phải là $ này không phải thế này (stackexchange sẽ không cho phép tôi thay đổi vì nó ít hơn 6 ký tự)
Richard Cleverley

Tôi sửa nó rồi. Xin lỗi vì điều đó
Marius

Tôi sẽ sử dụng một biến cục bộ cho cá thể người quan sát của bạn (giả sử nó là một singleton) hoặc một var cục bộ tĩnh cho chính phương thức đó so với sử dụng sổ đăng ký.
davidalger

@davidalger Bạn có thể giải thích một chút tại sao không? Tôi đã sử dụng đăng ký vì nó đường may tiện dụng nhất. Có bất kỳ lợi thế về việc sử dụng một var tĩnh?
Marius

@Marius Sử dụng sổ đăng ký về cơ bản là sử dụng biến toàn cục, nơi không cần thiết. Giữ nó được chứa bởi cá thể quan sát viên là sạch hơn. Vì vậy, chủ yếu là ngữ nghĩa, giải pháp của bạn hoạt động tuyệt vời. :)
davidalger

7

Bạn có thể hủy đăng ký một người quan sát sự kiện trên máy bay theo chương trình như sau:

$area = Mage::app()->getStore()->isAdmin() ? 'adminhtml' : 'frontend';
foreach (array($area, 'global') as $branch) {
    $path = $branch . '/events/customer_save_after/observers/your_module/type';
    Mage::app()->getConfig()->setNode($path, 'disabled');
}

Bạn không thể hủy đăng ký một sự kiện. Để tắt hoàn toàn một sự kiện, bạn sẽ phải lặp lại tất cả trẻ em $branch . '/events/customer_save_after/observers'và hủy kích hoạt từng sự kiện.

Nếu đó chỉ là một phương thức quan sát cụ thể mà bạn không muốn chạy lại, bạn có thể đặt loại đó thành singletonvà sau đó chỉ cần sử dụng thuộc tính boolean làm cờ để kiểm tra xem nó có được gọi một lần như sau không:

class Your_Module_Model_Observer
{
    private $_processFlag = false;

    public function customerSaveAfter($data)
    {
        if (! $this->_processFlag) {
            $this->_processFlag = true;
            // do your thing with $customer->save()
        }
    }
}

Sử dụng cờ hoặc đăng ký nó như được gửi đi có vẻ ít rắc rối nhất, thú vị để xem phương thức vô hiệu hóa vật lý mặc dù.
Richard Cleverley

1
Sử dụng sổ đăng ký gần giống như sử dụng biến toàn cục, tôi nghĩ rằng việc quản lý trạng thái trên cá thể người quan sát là đẹp hơn.
Vinai

Bạn có thể đúng thực sự. Giữ tất cả bản thân trong người quan sát theo cách đó có lẽ là cách tốt hơn để làm điều đó.
Richard Cleverley

1

đây là một phương pháp trợ giúp bằng chứng khái niệm làm đảo lộn một người quan sát hiện có. nếu bạn muốn tắt sự kiện này theo mặc định, hãy thêm <type>disabled</type>vào định nghĩa config.xml của người quan sát của bạn.

public function toggleObserver($area, $event, $name, $enable)
{
    $app = Mage::app();

    // reflection on the property Mage_Core_Model_App::_events
    $class = new ReflectionClass(get_class($app));
    $property = $class->getProperty('_events');
    $property->setAccessible(true);

    // get the events
    $events = $property->getValue($app);

    // make sure the event config is loaded
    if (!isset($events[$area][$event]))
    {
        // load observers from config
        /** @see Mage_Core_Model_App::dispatchEvent() */

        $config = $app->getConfig()->getEventConfig($area, $event);
        if (!$config)
        {
            // event is not configured
            return;
        }

        // create observers array
        $observers = array();
        foreach ($config->observers->children() as $name => $values)
        {
            $observers[$name] = array(
                'type'  => (string) $values->type,
                'model' => $values->class ? (string) $values->class : $values->getClassName(),
                'method'=> (string) $values->method,
                'args'  => (array) $values->args,
            );
        }
        $events[$area][$event]['observers'] = $observers;
    }

    if ($events[$area][$event] && isset($events[$area][$event]['observers'][$name]))
    {
        // enable/disable the observer by changing its type
        $events[$area][$event]['observers'][$name]['type'] = $enable ? '' : 'disabled';

        // update the object
        $property->setValue($app, $events);
    }
}

hàm sử dụng sự phản chiếu để truy cập vào thuộc tính được bảo vệ khác $_eventscủa Mage_Mage_Core_Model_App. thủ thuật tương tự có thể được sử dụng để tiêm cho các nhà quan sát chưa được xác định trước đó.

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.