2011-07-14 47 views

回答

8

下面是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) 
{ 

雖然某些事件有直接的名稱,如控制器相關predispatch和執行postDispatch事件,不僅事件發出特定的控制器一般事件,但還事件。一時間,看看preDispatch方法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) 

三個不同的事件在同一時間被髮射,並且可以對其中任何配置觀察員。

接下來,我們循環觀察者已註冊的事件區域和事件。事件區域可以是「前端」或「全局」,但這是一個內部概念,您不應該關心。

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

現在,通過觀察者循環。對於每個觀察者,根據其定義的類型(「model」,singleton「等)實例化觀察者的對象,然後調用_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; 
} 

達斯汀Oprea的

3

所有事件都通過Mage::dispatchEvent()。只需grep或ack以獲得「dispatchEvent」或您感興趣的事件名稱,您就會看到它的名稱。在該行上放置一個斷點。