Фильтруя сборы продуктов по атрибуту без флат
-
16-10-2019 - |
Вопрос
Я делаю следующее:
$productCollection = Mage::getModel('catalog/product')
->getCollection();
$productCollection
->addAttributeToFilter('my_attribute', 1);
my_attribute
не в плоских таблицах, но плоские таблицы включены.
Я продолжаю получать полную коллекцию.
Причина, кажется, в \Mage_Catalog_Model_Resource_Product_Collection::addAttributeToSelect
:
$columns = $this->getEntity()->getAttributeForSelect($attributeCode);
Нет $this->getEntity()
это случай Mage_Catalog_Model_Resource_Product_Flat
которые приносят плоские поля - и, если их не найдено, просто возвращает NULL.
Как чистый способ добавить атрибут без плата в фильтр сбора?
В моем случае это не чувствует, чтобы добавить атрибут к плоской таблице.
Решение
Вы можете присоединиться к необходимому столу самостоятельно.
$productCollection = Mage::getModel('catalog/product')
->getCollection();
$table = Mage::getSingleton('eav/config')->getAttribute('catalog_product', 'my_attribute')->getBackend()->getTable();
$attributeId = Mage::getSingleton('eav/config')->getAttribute('catalog_product', 'my_attribute')->getAttributeId();
$productCollection->getSelect()->join(array('attributeTable' => $table), 'e.entity_id = attributeTable.entity_id', array('my_attribute' => 'attributeTable.value'))
->where("attributeTable.attribute_id = ?", $attributeId)
->where("attributeTable.value = ?", 1);
Вы можете присоединиться к Store_id.
Другие советы
Взлом (CE 1.6.2.0+) состоит в том, чтобы передать условие как массив и верьте, хотите нет, что это работает как предполагалось:
$collection->addFieldToFilter(array(array('attribute' => 'my_attribute', 'eq' => 1)));
Причина, по которой работает Ответ Колинма, связана с кодом в app/code/core/Mage/Catalog/Model/Resource/Product/Collection.php
S. addAttributeToFilter
метод Если вы используете этот формат массива, он не звонит addAttributeToSelect
. Анкет В плоском режиме, addAttributeToSelect
молча терпит неудачу, если атрибут нет в плоской таблице.
(Ниже приведен переосмысление моего ответа на https://stackoverflow.com/questions/6271284/can-i-add-other-attributes-to-magentos-flat-product-catalog-table/17021620 - Я не уверен, что это за этикет, но знаю, что я бы нашел его полезным)
Я хотел «чистого» решения для выбора и фильтрации на атрибутах, не являющихся флатом, которые:
- Не требует, чтобы атрибут имел конкретные настройки в администраторе (он может быть добавлен пользователем или скрыт на передней части)
- работает как для плоского, так и для неплаттного режима
Я использовал соответствующую коллекцию продуктов, но это относится к любой коллекции EAV.
Неудачный код:
$_product = Mage::getModel('catalog/product')->loadByAttribute( 'sku', 'ABC123' );
$coll = $_product->getTypeInstance()->getAssociatedProductCollection()
->addAttributeToSelect( 'my_custom_attribute' )
->addAttributeToFilter( 'my_custom_attribute', 3 )
;
В плоском режиме приведенный выше код молча не может выбрать или фильтровать на атрибуте, если это произойдет не в плоской таблице.
Добавление к выбору:
$_product = Mage::getModel('catalog/product')->loadByAttribute( 'sku', 'ABC123' );
$coll = $_product->getTypeInstance()->getAssociatedProductCollection()
->joinAttribute( 'my_custom_attribute', 'catalog_product/my_custom_attribute', 'entity_id', null, 'left' )
->addAttributeToSelect( 'my_custom_attribute' )
;
А joinAttribute
Метод добавляет присоединение к запросу для конкретного запрошенного атрибута. Он по -прежнему работает, когда атрибут уже находится в плоской таблице, но будет немного менее эффективным, чем чисто используя плоскую таблицу.
Я использовал left
Присоединяйтесь туда, чтобы убедиться, что он получает продукты, если my_custom_attribute
не установлен на этих продуктах. Изменить это для inner
Если вы заинтересованы только в рядах, где my_custom_attribute
установлен.
Добавление к фильтру (согласно Колинму выше):
$_product = Mage::getModel('catalog/product')->loadByAttribute( 'sku', 'ABC123' );
$coll = $_product->getTypeInstance()->getAssociatedProductCollection()
->addAttributeToFilter( array( array( 'attribute' => 'my_custom_attribute', 'eq' => 3 ) ) )
;
Приведенный выше код добавит его в выбор, а также подчиняться вашему фильтру.
(Протестировано в CE 1.6.2.0)
в Mage_Rss
Модуль. Они используют тот факт, что плоские таблицы всегда выключены в магазине администратора, и поэтому просто подражают магазину администратора.
class Mage_Rss_Helper_Data {
[...]
/**
* Disable using of flat catalog and/or product model to prevent limiting results to single store. Probably won't
* work inside a controller.
*
* @return null
*/
public function disableFlat()
{
/* @var $flatHelper Mage_Catalog_Helper_Product_Flat */
$flatHelper = Mage::helper('catalog/product_flat');
if ($flatHelper->isEnabled()) {
/* @var $emulationModel Mage_Core_Model_App_Emulation */
$emulationModel = Mage::getModel('core/app_emulation');
// Emulate admin environment to disable using flat model - otherwise we won't get global stats
// for all stores
$emulationModel->startEnvironmentEmulation(0, Mage_Core_Model_App_Area::AREA_ADMINHTML);
}
}
После начала эмуляции вы должны сбросить ее с emulationModel->stopEnvironmentEmulation()
Когда вы создаете атрибут, он должен быть на глобальном уровне и отфильтруемый. Таким образом, это будет использоваться в индивидуальной навигации. Также это потребует, чтобы атрибут был раскрывающимся или многосекционным. Я бы лично посоветовал с изменением основных файлов в соответствии с вашими потребностями в этом случае