Events 如何在Magento中调试事件观察器?

Events 如何在Magento中调试事件观察器?,events,magento,observer-pattern,Events,Magento,Observer Pattern,我的观察者没有被召唤。我想知道事件是如何被调度的,以便我可以调试它。所有事件都通过Mage::dispatchEvent()。只需grep或“dispatchEvent”或您感兴趣的事件名称,您就会看到它的调用位置。在该行上放置一个断点。下面是Magento的Mage_Core_Model_App::dispatchEvent()调用的分解,该调用用于触发事件。我的注释将位于我正在描述的代码插入之前。我将省略那些显而易见的东西。值得一提的是,这是从Magento Enterprise 1.10.

我的观察者没有被召唤。我想知道事件是如何被调度的,以便我可以调试它。

所有事件都通过
Mage::dispatchEvent()
。只需grep或“dispatchEvent”或您感兴趣的事件名称,您就会看到它的调用位置。在该行上放置一个断点。

下面是Magento的Mage_Core_Model_App::dispatchEvent()调用的分解,该调用用于触发事件。我的注释将位于我正在描述的代码插入之前。我将省略那些显而易见的东西。值得一提的是,这是从Magento Enterprise 1.10.1.1的角度来看的

首先,这是整个方法定义:

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;
}
我们从宣言开始。将触发一个特定名称的事件,以及一些可选的支持数据

public function dispatchEvent($eventName, $args)
{
虽然有些事件具有简单的名称,但与控制器相关的预分派和后分派事件等事件不仅会发出常规事件,还会发出特定于控制器的事件。请看一下Mage_Core_Controller_Varien_操作中的预剥离方法:

    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)
同时发出三个不同的事件,您可以在其中任何一个事件上配置观察者

接下来,我们循环浏览观测者已注册的事件区域和事件。活动区域可以是“前端”或“全局”,但这是一个内部概念,您不应该关心

    foreach ($this->_events as $area=>$events) {
        if (!isset($events[$eventName])) {
获取此事件的派生配置。这本质上是一个XML节点,包含通过配置为此事件定义的所有观察者。除非为此事件定义了至少一个观察者,否则将找不到任何配置。在这种情况下,我们将$this->\u events[$area][$eventName]设置为FALSE,以后我们将通过上述条件绕过此检查

            $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;
否则,准备触发观察员。我们构建了一个Varien_事件作为事件的一个极其简单的容器,并构建了一个Varien_事件观察器来进一步包装它。这将作为参数发送给观察者

        } else {
            $event = new Varien_Event($args);
            $event->setName($eventName);
            $observer = new Varien_Event_Observer();
        }
现在,循环浏览观察者。对于每个观察者,根据其定义的类型(“model”,singleton等)实例化观察者的对象。然后,调用_callObserverMethod,确保该对象在调用它之前存在该方法。请注意,“singleton”类型的观察者属于下面的“default”情况

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

可以发布config.xml和包含观察者的模型类吗?