Magento не использует события перед загрузкой в функции сбора GETALLIDS
У меня есть вопрос о Magento, который я не знаю, является ли это ошибкой или нет.
Коллекция категорий:
Я использовал наблюдателя для фильтрации только категорий клиентов (бизнес-правило)
My_Module/config.xml
<frontend>
<events>
<catalog_category_collection_load_before>
<observers>
<my_module>
<type>model</type>
<class>my_module/catalog_observer</class>
<method>removeUnavailableCategories</method>
</my_module>
</observers>
</catalog_category_collection_load_before>
</events>
</frontend>
My_Module/Model/Catalog/Observer.php
<?php
class My_Module_Model_Catalog_Observer
{
function removeUnavailableCategories($observer)
{
$collection = $observer->getCategoryCollection();
$allowedCategories = array();
foreach (Mage::helper('my_module/customer')->getAllowedCategories() as $category)
{
$allowedCategories[]['like'] = $category->getPath();
$allowedCategories[]['like'] = $category->getPath() . '/%';
}
if (count($allowedCategories) > 0)
{
$collection->addFieldToFilter('path', $allowedCategories);
}
else
{
/**
* Clear collection
*/
$collection->getSelect()->reset(Zend_Db_Select::WHERE);
$collection->getSelect()->where('e.entity_id < 0');
}
}
}
Как вы можете видеть, я поставил фильтр, чтобы показывать только категории, разрешенные для клиента.
Но, когда я использую функцию "Getallids" в коллекции категорий, это наблюдатель не вызывается:
Mage::getModel('catalog/category')->getCollection()->getAllIds();
Я делаю это так:
Mage::getModel('catalog/category')->getCollection()->load()->getAllIds();
И это сработало.
Но мне это не нравится. Так как функция "Getallids" снова выполняет поиск:
mage_eav_model_entity_collection_abstract
маг_еав_модель_событий_коллекции_абстратprotected function _getAllIdsSelect($limit = null, $offset = null)
{
$idsSelect = clone $this->getSelect();
$idsSelect->reset(Zend_Db_Select::ORDER);
$idsSelect->reset(Zend_Db_Select::LIMIT_COUNT);
$idsSelect->reset(Zend_Db_Select::LIMIT_OFFSET);
$idsSelect->reset(Zend_Db_Select::COLUMNS);
$idsSelect->columns('e.' . $this->getEntity()->getIdFieldName());
$idsSelect->limit($limit, $offset);
return $idsSelect;
}
public function getAllIds($limit = null, $offset = null)
{
return $this->getConnection()->fetchCol($this->_getAllIdsSelect($limit, $offset), $this->_bindParams);
}
Мой вопрос таков:
Правильно ли использовать вызов функции _beforeLoad перед поиском идентификаторов?
Вот так:
public function getAllIds($limit = null, $offset = null)
{
$this->_beforeLoad();
return $this->getConnection()->fetchCol($this->_getAllIdsSelect($limit, $offset), $this->_bindParams);
}
ИЛИ
protected function _getAllIdsSelect($limit = null, $offset = null)
{
$this->_beforeLoad();
$idsSelect = clone $this->getSelect();
$idsSelect->reset(Zend_Db_Select::ORDER);
$idsSelect->reset(Zend_Db_Select::LIMIT_COUNT);
$idsSelect->reset(Zend_Db_Select::LIMIT_OFFSET);
$idsSelect->reset(Zend_Db_Select::COLUMNS);
$idsSelect->columns('e.' . $this->getEntity()->getIdFieldName());
$idsSelect->limit($limit, $offset);
return $idsSelect;
}
Или есть что-то, чего я не знаю?
1 answers
Это предполагаемое поведение. getAllIds()
предназначен для использования для одного запроса COUNT() и фактически не загружает коллекцию. Таким образом, запуск события перед загрузкой не имеет семантического смысла.
Я бы не рекомендовал переписывать модель категорий, чтобы всегда вызывать _beforeLoad()
, как вы предложили, потому что это может привести к нежелательным побочным эффектам.
С другой стороны, я понимаю, почему вы этого хотите, потому что большую часть времени вы меняете фильтры в этом событии и было бы полезно иметь их в запросе count.
Возможное решение состоит в том, чтобы переместить фактическую логику фильтра из наблюдателя в другой класс (может быть помощником) и вызвать ее из наблюдателя, а также в тех местах, где вы используете getAllIds()
в своем коде.