Фільтруйте колекцію продуктів за не плоским атрибутом


14

Я роблю наступне:

$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.

Який чистий спосіб додати неплоский атрибут до фільтру колекції?

У моєму випадку не має сенсу додавати атрибут до плоскої таблиці.


Вітаю, сер, Ви хотіли вирішити плутанину ?? ВАТ означає серед non-flat attribute? Дякую. І не робіть магенто заплутаним. Це вже заплутано
Пратік

Я говорю про атрибути, які не входять в плоский індекс. Це ті, для яких "Використовується в лістингу продуктів" встановлено значення "Ні".
Олексій

Відповіді:


18

Ви можете самостійно приєднатися до потрібної таблиці.

$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.


Думаю, у мене все ще виникне проблема, що я не отримую продукцію всіх магазинів. (коли б спочатку я не бачив цієї проблеми у своєму питанні). Схоже, я хочу повністю відключити плоскі індекси.
Алекс

Якщо вам потрібні всі продукти, то плоскі столи не будуть вашими друзями, так.
Маттіас Зейс

Я думаю, ви можете змінити своє запитання або прийняти мою відповідь (що працює на оригінальне запитання).
Маттіас Зейс

приголомшливий .. концепція
Аміт Бера

15

Хак (CE 1.6.2.0+) - це передати умову як масив і повірити, чи це не працює, як задумано:

$collection->addFieldToFilter(array(array('attribute' => 'my_attribute', 'eq' => 1)));

Будь-яка підказка, чому це працює?
Олексій

3
Це працює, тому що для колекції eav addFieldToFiler- це обгортка, addAttributeToFilterі у неї є можливість передавати атрибут як масив:if (is_array($attribute)) { $sqlArr = array(); foreach ($attribute as $condition) { $sqlArr[] = $this->_getAttributeConditionSql($condition['attribute'], $condition, $joinType); } $conditionSql = '('.implode(') OR (', $sqlArr).')'; }
Marius

@Marius, це означає, що це не хак? : P Чи можу я відчувати себе добре від його використання?
Ерфан

3
@Erfan. це не хак. це особливість.
Маріус

Солодке. Це все ще дивно, що реалізація таблиці продуктів (eav / flat) не відбирається для речей так просто, як фільтрування колекції. Чи означає це, що мені завжди потрібно використовувати addFieldToFilter замість addAttributeToFilter у своєму коді, тому що я не знаю, чи використовується он-лайн чи flat? В чому сенс addAttributeToFilter?
Ерфан

6

Причина відповідь ColinM працює з - за код в app/code/core/Mage/Catalog/Model/Resource/Product/Collection.php«s addAttributeToFilterметоду. Якщо ви використовуєте цей формат масиву, він не дзвонить addAttributeToSelect. У плоскому режиміaddAttributeToSelect мовчки виходить з ладу, якщо атрибут не знаходиться в плоскій таблиці.

(нижче - повторна відповідь моєї відповіді на /programming/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' )
;

The joinAttributeМетод додає приєднатися до запиту для атрибута конкретного запитаного. Він все ще працює, коли атрибут вже знаходиться в плоскій таблиці, але буде дещо менш ефективним, ніж просто використання плоскої таблиці.

Я використовував там leftз'єднання, щоб переконатися, що він отримує продукти, якщоmy_custom_attribute їх не встановлено. Змініть це, innerякщо вас цікавлять лише рядки, де my_custom_attributeвстановлено.

Додавання до фільтра (відповідно до ColinM вище):

$_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)


4

У 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()


Де ця відповідь була 3 дні тому? ; _;
sg3s

Саме тут? З 20 березня
Олексій

1

коли ви створюєте атрибут, він повинен бути на глобальному рівні та фільтрувати. Таким чином він стане корисним у пластовій навігації. Крім того, він вимагає атрибуту бути спадним або мультиселекторним. Я особисто радив би не змінювати основні файли відповідно до ваших потреб у цьому випадку


Я не хочу, щоб атрибут у фронтальному фільтрі - я просто хочу зробити фільтрацію колекції для внутрішнього використання.
Алекс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.