events - 如何在 Magento 中调试我的事件观察器?

标签 events magento observer-pattern

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

最佳答案

这是 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)
{

虽然有些事件的名称很简单,但像 Controller 相关的 predispatch 和 postdispatch 事件这样的事件不仅发出一般事件,还发出特定于 Controller 的事件。一会儿看一下Mage_Core_Controller_Varien_Action中的preDispatch方法:
    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->_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_Event 作为事件的一个非常简单的容器,以及一个进一步包装它的 Varien_Event_Observer。这作为参数发送给观察者。
        } else {
            $event = new Varien_Event($args);
            $event->setName($eventName);
            $observer = new Varien_Event_Observer();
        }

现在,循环查看观察者。对于每个观察者,根据其定义的类型(“模型”、单例等)实例化观察者的对象。然后,调用 _callObserverMethod,这确保在调用该对象之前存在该对象的方法。注意类型的观察者“单例”属于下面的“默认”情况。
        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;
}

关于events - 如何在 Magento 中调试我的事件观察器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6693448/

相关文章:

css - Magento 1.9.1 - 安装期间未加载 CSS

Java:找出哪个观察者正在监听

f# - 可变状态和观察者模式

Java:可以通过观察者层次结构向观察者通知更改吗?

jQuery:触发(mousemove 或 "keypressed")

c# - HttpModule 中的异步事件处理程序

.net - Async.AwaitEvent 在调用基础事件后不会取消

php - Magento2 knockout 渲染特定子项

events - 使用Spring Security Core插件和Grails 2.0.0注册事件监听器时出错

mysql - 如何与 Magento Commerce 进行数据库访问 (I/O)?