开发者

How can I debug my event observer in Magento?

My observer isn't being called. I'd like to know how events get dispatched so that I can deb开发者_Go百科ug it.


Here's a breakdown of Magento's Mage_Core_Model_App::dispatchEvent() call, which is what is used to trigger events. My comments will precede the code inset that I'm describing. I'll leave out the obvious stuff. It's worth mentioning that this is from the perspective of Magento Enterprise 1.10.1.1 .

To start with, this is the whole method definition:

public function dispatchEvent($eventName, $args)
{
    foreach ($this->_events as $area=>$events) {
        if (!isset($events[$eventName])) {
            $eventConfig = $this->getConfig()->getEventConfig($area, $eventName);
            if (!$eventConfig) {
                $this->_events[$area][$eventName] = false;
                continue;
            }
            $observers = array();
            foreach ($eventConfig->observers->children() as $obsName=>$obsConfig) {
                $observers[$obsName] = array(
                    'type'  => (string)$obsConfig->type,
                    'model' => $obsConfig->class ? (string)$obsConfig->class : $obsConfig->getClassName(),
                    'method'=> (string)$obsConfig->method,
                    'args'  => (array)$obsConfig->args,
                );
            }
            $events[$eventName]['observers'] = $observers;
            $this->_events[$area][$eventName]['observers'] = $observers;
        }
        if (false===$events[$eventName]) {
            continue;
        } else {
            $event = new Varien_Event($args);
            $event->setName($eventName);
            $observer = new Varien_Event_Observer();
        }

        foreach ($events[$eventName]['observers'] as $obsName=>$obs) {
            $observer->setData(array('event'=>$event));
            Varien_Profiler::start('OBSERVER: '.$obsName);
            switch ($obs['type']) {
                case 'disabled':
                    break;
                case 'object': case 'model':
                    $method = $obs['method'];
                    $observer->addData($args);
                    $object = Mage::getModel($obs['model']);
                    $this->_callObserverMethod($object, $method, $observer);
                    break;
                default:
                    $method = $obs['method'];
                    $observer->addData($args);
                    $object = Mage::getSingleton($obs['model']);
                    $this->_callObserverMethod($object, $method, $observer);
                    break;
            }
            Varien_Profiler::stop('OBSERVER: '.$obsName);
        }
    }
    return $this;
}

We begin at the declaration. An event of a specific name is fired, along with some optional supporting data to include along with it.

public function dispatchEvent($eventName, $args)
{

Whereas some events have straightforward names, events like the controller-related predispatch and postdispatch events not only emit the general events, but also events specific to the controller. For a moment, look at the preDispatch method in Mage_Core_Controller_Varien_Action:

    Mage::dispatchEvent('controller_action_predispatch', array('controller_action'=>$this));
    Mage::dispatchEvent(
        'controller_action_predispatch_'.$this->getRequest()->getRouteName(),
        array('controller_action'=>$this)
    );
    Mage::dispatchEvent(
        'controller_action_predispatch_'.$this->getFullActionName(),
        array('controller_action'=>$this)

Three different events are emitted at the same time, and you can configure observers on any of them.

Next, we cycle through the event-areas and events that observers have been registered for. An event-area can be either "frontend" or "global", but this is an internal concept that you shouldn't be concerned with.

    foreach ($this->_events as $area=>$events) {
        if (!isset($events[$eventName])) {

Get the derived configuration for this event. This is essentially an XML node containing all of the observers that have been defined for this event through configuration. No configuration will be found unless there's at least one observer defined for this event. In that case, we set $this->_events[$area][$eventName] to FALSE, and we'll bypass this check in the future via the conditional above.

            $eventConfig = $this->getConfig()->getEventConfig($area, $eventName);
            if (!$eventConfig) {
                $this->_events[$area][$eventName] = false;
                continue;
            }

Construct an array of registered observers.

            $observers = array();
            foreach ($eventConfig->observers->children() as $obsName=>$obsConfig) {
                $observers[$obsName] = array(
                    'type'  => (string)$obsConfig->type,
                    'model' => $obsConfig->class ? (string)$obsConfig->class : $obsConfig->getClassName(),
                    'method'=> (string)$obsConfig->method,
                    'args'  => (array)$obsConfig->args,
                );
            }
            $events[$eventName]['observers'] = $observers;
            $this->_events[$area][$eventName]['observers'] = $observers;
        }

If no observers were found either in this pass or previous passes, loop.

        if (false===$events[$eventName]) {
            continue;

Else, prepare to trigger the observers. We build a Varien_Event as an extremely simple container for the event, and a Varien_Event_Observer that further wraps it. This is sent as an argument to the observer.

        } else {
            $event = new Varien_Event($args);
            $event->setName($eventName);
            $observer = new Varien_Event_Observer();
        }

Now, cycle through the observers. For each observer, instantiate the observer's object based on its defined type ("model", singleton", etc..). Then, call _callObserverMethod, which makes sure the method exists for that object before invoking it. Note that an observer of type "singleton" falls into the "default" case below.

        foreach ($events[$eventName]['observers'] as $obsName=>$obs) {
            $observer->setData(array('event'=>$event));
            Varien_Profiler::start('OBSERVER: '.$obsName);
            switch ($obs['type']) {
                case 'disabled':
                    break;
                case 'object': case 'model':
                    $method = $obs['method'];
                    $observer->addData($args);
                    $object = Mage::getModel($obs['model']);
                    $this->_callObserverMethod($object, $method, $observer);
                    break;
                default:
                    $method = $obs['method'];
                    $observer->addData($args);
                    $object = Mage::getSingleton($obs['model']);
                    $this->_callObserverMethod($object, $method, $observer);
                    break;
            }
            Varien_Profiler::stop('OBSERVER: '.$obsName);
        }
    }
    return $this;
}


All events pass through Mage::dispatchEvent(). Simply grep or ack for "dispatchEvent" or the event name you're interested in and you'll see where it is called. Place a breakpoint on that line.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜