Отменить регистрацию наблюдателя событий программно


Кто-нибудь знает, можно ли отменить регистрацию наблюдателя событий программно? У меня есть наблюдатель на newsletter_subscribe_save_after, который обновляет пользовательский атрибут в модели клиента, но когда запись клиента сохраняется, она запускает событие customer_save_after, определенное в Mage_All.xml, которое затем повторно сохраняет статус подписки на новостную рассылку, что приводит к бесконечному циклу, который затем запускает ошибку рекурсии PHP из-за вложенности 100 раз.

В идеале я хотел бы отменить регистрацию события customer_save_after только когда мой наблюдатель стреляет.

Author: Marius, 2013-07-10

3 answers

Вы можете попытаться пометить свое событие как dispatched и при второй попытке запустить его просто ничего не делайте, если оно уже отправлено. Например, предположим, что ваш метод называется 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.
}

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

 10
Author: Marius, 2013-07-10 20:53:16

Вы можете отменить регистрацию события наблюдатель на лету программно следующим образом:

$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');
}

Вы не можете отменить регистрацию самого события. Чтобы полностью деактивировать событие, вам придется зациклиться на всех дочерних элементах $branch . '/events/customer_save_after/observers' и деактивировать каждый из них.

Если это всего лишь один конкретный метод наблюдателя, который вы не хотите запускать снова, вы можете установить его тип singleton, а затем просто использовать логическое свойство в качестве флага, чтобы проверить, был ли он уже вызван один раз следующим образом:

class Your_Module_Model_Observer
{
    private $_processFlag = false;

    public function customerSaveAfter($data)
    {
        if (! $this->_processFlag) {
            $this->_processFlag = true;
            // do your thing with $customer->save()
        }
    }
}
 7
Author: Vinai, 2015-09-02 15:00:18

Вот вспомогательный метод доказательства концепции, который переключает существующего наблюдателя. если вы хотите, чтобы событие было отключено по умолчанию, добавьте <type>disabled</type> в список вашего наблюдателя config.xml определение.

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

Функция использует отражение для доступа к защищенному в противном случае свойству $_events Mage_Mage_Core_Model_App. Тот же трюк может быть использован для введения ранее неопределенных наблюдателей.

 1
Author: alternize, 2015-01-22 23:10:49