按非固定属性过滤产品集合


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

No $this->getEntity()Mage_Catalog_Model_Resource_Product_Flat获取平面字段的实例-如果找不到,则返回null。

什么是向集合过滤器添加非扁平属性的干净方法?

就我而言,将属性添加到平面表是没有意义的。


嗨,先生,您是否想解决混乱问题?WAT是什么意思non-flat attribute?谢谢。不要让magento令人困惑。它已经令人困惑
Pratik 2014年

我说的是不在平面索引中的属性。这些是将“产品列表中使用的商品”设置为“否”的商品。
亚历克斯(Alex)

Answers:


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加入。


我想我仍然会有一个问题,那就是我没有得到所有商店的产品。(只要我本来没有在问题中看到此问题)。看起来我想完全禁用平面索引。
Alex

如果您需要所有产品,那么平板便不会成为您的朋友,是的。
Matthias Zeis

我想您可能想要修改您的问题或接受我的答案(适用于原始问题)。
Matthias Zeis 2013年

awasome .. concept
Amit Bera

15

骇客(CE 1.6.2.0+)会将条件作为数组传递,并且不管它是否按预期工作:

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

任何线索为什么可行?
亚历克斯

3
它之所以起作用,addFieldToFiler是因为eav集合是包装器,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我可以很好地使用它吗?
Erfan 2014年

3
@Erfan。这不是黑客。这是一个功能。
马里乌斯

甜。产品表实现(eav / flat)并没有像过滤集合这样简单的事情被抽象出来,这仍然有点奇怪。这是否意味着我总是需要在代码中使用addFieldToFilter而不是addAttributeToFilter,因为我不知道它是使用eav还是flat?无论如何,addAttributeToFilter有什么意义?
Erfan 2014年

6

究其原因ColinM的答案的工作原理是由于代码app/code/core/Mage/Catalog/Model/Resource/Product/Collection.phpaddAttributeToFilter方法。如果您使用此数组格式,则不会调用addAttributeToSelect。在平面模式下,addAttributeToSelect如果属性不在平面表中,则静默失败。

(以下是我在/programming/6271284/can-i-add-other-attributes-to-magentos-flat-product-catalog-table/17021620上的答案的哈希值-我是不知道这是什么礼节,但知道我会发现这很有帮助)

我想要一个“干净”的解决方案,用于平面模式集合选择和过滤非平面属性,该解决方案:

  • 不需要该属性在admin中具有特定设置(它可以由用户添加或隐藏在前端)
  • 适用于平面和非平面模式

我使用了相关的产品集合,但这适用于任何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设置位置的行感兴趣,请更改此设置。

添加到过滤器中(根据上述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模块中,他们使用了一种hacky方法来禁用平面表。他们使用这样的事实:平面表始终在管理存储区中处于关闭状态,因此仅模拟管理存储区。

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

就在这儿?自3月20
Alex

1

创建属性时,该属性应该在全局级别且可过滤。这样,它将可在分行导航中使用。此外,它将要求该属性为下拉列表或多选。在这种情况下,我个人建议不要更改核心文件以满足您的需求


我不需要前端过滤器中的属性-我只想做一个集合过滤以供内部使用。
亚历克斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.