Как я могу отладить моего наблюдателя событий в Magento? - PullRequest
3 голосов
/ 14 июля 2011

Моего наблюдателя не вызывают. Я хотел бы знать, как события отправляются, чтобы я мог их отладить.

Ответы [ 2 ]

9 голосов
/ 18 июля 2011

Вот разбивка вызова 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();
        }

Теперь переберите наблюдателей. Для каждого наблюдателя создайте экземпляр объекта наблюдателя на основе его определенного типа («модель», singleton »и т. Д.). Затем вызовите _callObserverMethod, чтобы убедиться, что метод существует для этого объекта, прежде чем вызывать его. Обратите внимание, что наблюдатель типа "singleton" относится к случаю "по умолчанию" ниже.

        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;
}
3 голосов
/ 14 июля 2011

Все события проходят через Mage::dispatchEvent(). Просто grep или ack для "dispatchEvent" или имени интересующего вас события, и вы увидите, как оно вызывается. Поместите точку останова на этой линии.

...