سؤال

Does anyone know if it's possible to unregister an event observer programatically? I have an observer on newsletter_subscribe_save_after that updates a custom attribute in the customer model but when the customer record is saved it triggers off the customer_save_after event defined in Mage_All.xml which then re-saves the newsletter subscription status resulting in an infinite loop that then triggers the PHP recursion error due to nesting 100 times.

Ideally I'd like to unregister the customer_save_after event only when my observer fires.

هل كانت مفيدة؟

المحلول

You can try to mark your event as dispatched and on the second attempt of running it just do nothing if it's already dispatched. For example let's say your method is called 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.
}

The registry key name is not important, just make sure you use the same one in both cases.

نصائح أخرى

You can unregister an event observer on the fly programmatically as follows:

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

You can not unregister an event itself. To completely deactivate an event, you would have to loop over all children of $branch . '/events/customer_save_after/observers' and deactivate each one.

If it's just a single specific observer method you don't want to run again, you can set it's type to be singleton and then just use a boolean property as a flag to check if it already was called once as follows:

class Your_Module_Model_Observer
{
    private $_processFlag = false;

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

here's a proof-of-concept helper method that toggles an existing observer. if you want to have the event disabled as default, add <type>disabled</type> to your observer's config.xml definition.

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

the function makes use of reflection to access the otherwise protected $_events property of Mage_Mage_Core_Model_App. the same trick could be used to inject previously undefined observers.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى magento.stackexchange
scroll top