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

Или есть что-то, чего я не знаю?

Author: Fabian Schmengler, 2016-03-21

1 answers

Это предполагаемое поведение. getAllIds() предназначен для использования для одного запроса COUNT() и фактически не загружает коллекцию. Таким образом, запуск события перед загрузкой не имеет семантического смысла.

Я бы не рекомендовал переписывать модель категорий, чтобы всегда вызывать _beforeLoad(), как вы предложили, потому что это может привести к нежелательным побочным эффектам.

С другой стороны, я понимаю, почему вы этого хотите, потому что большую часть времени вы меняете фильтры в этом событии и было бы полезно иметь их в запросе count.

Возможное решение состоит в том, чтобы переместить фактическую логику фильтра из наблюдателя в другой класс (может быть помощником) и вызвать ее из наблюдателя, а также в тех местах, где вы используете getAllIds() в своем коде.

 1
Author: Fabian Schmengler, 2016-03-21 16:00:12