Шаблон события/наблюдателя нарушен переопределением метода _beforeSave() в нескольких классах Magento, которые расширяют Mage_Core_Model_Abstract

Пытаясь реализовать наблюдатель для перехвата событий 'cataloginventory_stock_item_save_before', я понял, что метод _beforeSave() в Mage_CatalogInventory_Model_Stock_Item переопределяет метод Mage_Core_Model_Abstract без вызова его родителя, тем самым не позволяя системе отправлять обычные 'model_save_before' и $this->_eventPrefix.'_save_before'события...

In Mage_Core_Model_Abstract:

protected function _beforeSave()
{
    //...
    Mage::dispatchEvent('model_save_before', array('object'=>$this));
    Mage::dispatchEvent($this->_eventPrefix.'_save_before', $this->_getEventData());
    return $this;
}

In Mage_CatalogInventory_Model_Stock_Item:

protected function _beforeSave()
{
    //...some other stuff, but no parent::_beforeSave()!
    return $this;
}

Хотя я очень новичок в Magento, это выглядит странно для меня, особенно когда я смотрю на многие другие классы Magento, которые расширяют Mage_Core_Model_Abstract, переопределяют метод _beforeSave(), но делают вызов parent::_beforeSave() (по-разному, как и можно увидеть на следующих примерах).

Например, в Mage_Catalog_Model_Product:

protected function _beforeSave()
{
    //...
    parent::_beforeSave();
    //no return in this one!
}

In Mage_Catalog_Model_Product_Compare_Item:

protected function _beforeSave()
{
    parent::_beforeSave();
    //...
    return $this;
}

Or in Mage_Catalog_Model_Abstract:

protected function _beforeSave()
{
    //...
    return parent::_beforeSave();
}

И т.п.

Что еще более странно, Mage_CatalogInventory_Model_Stock_Item также переопределяет _afterSave(), но на этот раз вызывает метод родителя:

In Mage_CatalogInventory_Model_Stock_Item:

protected function _afterSave()
{
    parent::_afterSave();
    //...
    return $this;
}

Мой вопрос (предназначен для гуру Magento):
Вы понимаете, есть ли какая-то веская причина для этого пропуска parent::_beforeSave() в Mage_CatalogInventory_Model_Stock_Item?
Или это должно быть указано как ошибка? ?

Единственное исправление, о котором я подумал, чтобы иметь возможность перехватывать события 'cataloginventory_stock_item_save_before', состоит в том, чтобы скопировать весь класс Mage_CatalogInventory_Model_Stock_Item из core в local и добавить вызов либо в parent::_beforeSave(), либо непосредственно в Mage::dispatchEvent('cataloginventory_stock_item_save_before', ...).
Разве это не так? решение плохой взлом?

Поискав (просто из любопытства) множество других прямых потомков Mage_Core_Model_Abstract, я обнаружил, что наряду с Mage_CatalogInventory_Model_Stock_Item только два других подкласса имеют ту же проблему, по крайней мере, что касается метода _beforeSave() (я не проверял другие основные события, такие как _afterSave и т. д.): Mage_XmlConnect_Model_Application``andMage_Dataflow_Model_Batch`.
Что наводит меня на мысль, что это упущение только в трех классах могло быть сделано непреднамеренно...

Итак: это баг или я ошибаюсь?


person tpiazzapw    schedule 29.08.2012    source источник


Ответы (1)


Не уверен, что имеется в виду под "безе" в данном контексте, но это один из нескольких примеров, в которых целевые Mage_Core_Model_Abstract автоматически запускаемые события...

  • *_load_before
  • *_load_after
  • *_delete_before
  • *_delete_after
  • *_delete_commit_after
  • *_save_before
  • *_save_after
  • *_save_commit_after

...сломаны.

Это происходит либо из-за того, что подкласс не может вызвать метод родительского шаблона при переопределении (как вы упомянули), либо из-за того, что не удалось переопределить _eventPrefix в подклассе. Мне это всегда казалось скорее упущением, чем намерением.

В данном случае Mage_CatalogInventory_Model_Stock_Item::_beforeSave() это кажется упущением. Вверх по версия 1.3.2.4 этого класса метод дублирует целевую логику события (хотя он пропускает отправку model_save_before). версия 1.4.0.0-alpha2 этого файла видит добавленное свойство _eventPrefix, хотя сбой вызова родительского метода _beforeSave() приводит к потере этого целевого события.

Единственное намерение, которое я вижу в этом случае, может заключаться в том, чтобы заставить разработчика манипулировать объектом cataloginventory как свойством stock_item в контексте процесса сохранения продукта, но это заслуживает комментария к коду.

person benmarks    schedule 29.08.2012
comment
Извините за использование этой глупой шотландской шутки о меренге... ;-) - person tpiazzapw; 29.08.2012
comment
Спасибо за ваш подробный ответ! Я рад видеть, что не совсем сбился с пути. Как и вы, я обнаружил в истории git исчезновение диспетчеризации событий. Существование этой диспетчеризации в версиях до 1.4 заставило меня задуматься, была ли веская причина для ее удаления... - person tpiazzapw; 29.08.2012
comment
В любом случае, вы согласны с тем, что единственное исправление — это скопировать весь класс из ядра в локальный и исправить его? - person tpiazzapw; 29.08.2012
comment
Теперь у вас достаточно репутации, чтобы проголосовать, ваш вопрос был полезен для меня, как и ответ, но это был мой последний голос на сегодня;) - person Yaroslav; 26.09.2012
comment
Даже в версии 1.7.0.2 метод parent::_beforeSave(); отсутствует в Mage_CatalogInventory_Model_Stock_Item::_beforeSave(), и туда не отправляется ни одно событие. - person PvdL; 07.02.2013