複数のカテゴリで製品コレクションをフィルタリングしますか?


7

最近追加された製品を取得する次のコードスニペットがあります。

$_productCollection = Mage::getResourceModel('catalog/product_collection')
                ->addAttributeToSelect('*')
                ->addAttributeToFilter($preorderAttribute, array(
                    'eq' => Mage::getResourceModel('catalog/product')
                        ->getAttribute($preorderAttribute)
                        ->getSource()
                        ->getOptionId($preorderValue)
                ))
                ->setVisibility(array(2,3,4))
                ->setOrder('created_at', 'desc')
                ->setPage(1, 12);

これをさらにカテゴリ(たとえば、ID 3および4のカテゴリ)でフィルタリングしたいと思います。コレクションでは、3および4カテゴリの製品のみが選択されています。どうすればこれを達成できますか?

addAttributeToFilterカテゴリIDでフィルタリングするためにを使用しようとしましたが、それを行うにはさまざまな方法があり、機能していないか、単に致命的なエラーが発生するだけです。

非メンバー関数getBackend()の呼び出し

....今、私は途方に暮れています。

任意の助けいただければ幸いです。

回答:


22

次のコード例は、特定の2つのカテゴリ(7および8)の製品のみを表示するために機能します。それがあなたのためにうまくいくことを願っています:

$productCollection = Mage::getModel('catalog/product')
    ->getCollection()
    ->joinField(
        'category_id', 'catalog/category_product', 'category_id', 
        'product_id = entity_id', null, 'left'
    )
    ->addAttributeToSelect('*')
    ->addAttributeToFilter('category_id', array(
            array('finset' => array('7', '8', )),
    ))
    ->addAttributeToSort('created_at', 'desc');

foreach($productCollection as $product){
    echo $product->getId() . "<br/>\n";
};

3
+1完璧。ところで、「finset」の代わりに「in」を使用することもできます。したがって、以下のようになります$ _productCollection-> addAttributeToFilter( 'category_id'、array( 'in' => array( '106'、 '107'、 '108'、 '110')))
Haijerome

2
フィルタリングするカテゴリが2つ以上あり、製品がこれらのカテゴリの複数に割り当てられている場合、このコードは機能しません。エラーをとして返しますItem (Mage_Catalog_Model_Product) with the same id "xx" already exist
MTM 2014年

1
商品ごとにグループ化することで、複数のカテゴリの商品がある場合に対応でき$productCollection->getSelect()->group('e.entity_id');ます。グループ化を追加すると、コレクション数などの一部の機能が無効になることに注意してください。
Robert Egginton、2016

また、上記のコードは、結合のバインド変数で空白が取り除かれていない古いバージョンのMagentoでは機能しないため、条件が必要です'product_id=entity_id'-スペースがないことに注意してください。
Robert Egginton、2016

あなたは何回か同じ製品apprearing持つことができるよう、実際にあなたがまだ必要があります@Haijerom編集を言ったように、あなたが「中」を使用した場合のグループする必要はありません
Erdal G.

4

別の選択肢:

この例で$categoryIdsは、はカテゴリIDの配列です。(私は通常使用して$collection->getFlag('category_ids')いますが、この例では変更しました。下の説明を参照してください)

$currentStoreId現在のストアIDを取得できる任意の方法で入力されます。(私が使用する私のオブザーバーイベントで$collection->getFlag('store_id')

$conditions = array(
    'cat_index.product_id=e.entity_id',
    $collection->getConnection()->quoteInto('cat_index.category_id IN (' . $categoryIds . ')', "")
);
if (!Mage::app()->getStore()->isAdmin()) {
    $conditions[] = $collection->getConnection()->quoteInto('cat_index.store_id=?', $currentStoreId );
}
$joinCond = join(' AND ', $conditions);
$fromPart = $collection->getSelect()->getPart(Zend_Db_Select::FROM);

if (isset($fromPart['cat_index'])) {
    $fromPart['cat_index']['joinCondition'] = $joinCond;
    $collection->getSelect()->setPart(Zend_Db_Select::FROM, $fromPart);
} else {
    $collection->getSelect()->join(
            array('cat_index' => $collection->getTable('catalog/category_product_index')), $joinCond, array('cat_index_category_id' => 'category_id')
    );
}

上記のコードをオブザーバーで使用して、組み込みの呼び出しMage_Catalog_Model_Resource_Product_Collection::_applyProductLimitations()が実行した後、複数のカテゴリでフィルタリングします。'catalog_product_collection_apply_limitations_after'

この_applyProductLimitationsメソッドは基本的に、の呼び出しによって設定されたフィルターを適用しaddCategoryFilterます。

でフラグを使用する$collectionと、オブザーバーの複数のカテゴリIDを格納するのが簡単になります。

したがって、複数のカテゴリでフィルタリングする必要があるときはいつでも、ある時点でコレクションにフラグを設定します

例は書き換えることです Mage_Catalog_Model_Category::getProductCollection()

public function getProductCollection() {
    $collection = parent::getProductCollection();
    $collection->setFlag('category_ids',array(19,243,42,54)); //the array of values can be from somehwre, this hard coded array serves purely as an example
    return $collection;    
}

ここで、magentoがイベントを発生させると、私のコードはカテゴリーフィルターを複数のフィルターに置き換えます:)

これは基本的に、私の動的カテゴリ製品モジュールが複数のカテゴリフィルタに対して機能する方法です。

RefのコアコードaddCategoryFilter

/**
 * Specify category filter for product collection
 *
 * @param Mage_Catalog_Model_Category $category
 * @return Mage_Catalog_Model_Resource_Product_Collection
 */
public function addCategoryFilter(Mage_Catalog_Model_Category $category)
{
    $this->_productLimitationFilters['category_id'] = $category->getId();
    if ($category->getIsAnchor()) {
        unset($this->_productLimitationFilters['category_is_anchor']);
    } else {
        $this->_productLimitationFilters['category_is_anchor'] = 1;
    }

    if ($this->getStoreId() == Mage_Catalog_Model_Abstract::DEFAULT_STORE_ID) {
        $this->_applyZeroStoreProductLimitations();
    } else {
        $this->_applyProductLimitations();
    }

    return $this;
}

2

@monojit banikと@ProxiBlueの両方の回答で提供されている手法を使用して、@ MTMのコメントで識別された「同じID "xx"のアイテム(Mage_Catalog_Model_Product)が既に存在します "というエラーが両方にありました。

レイヤードナビゲーションでのコレクションの負荷の外で発生するエラーを回避するために、2つの異なる方法で1回のパスで異なる製品のセットを取得しようとしましたが、何もうまくいきませんでした。

最終的に、(編集:このブログ投稿に基づいて、https://www.muddyweb.com/general-ramblings/filtering-a-magento-product-collection-by-multiple-categories/)2つの別々のコレクションロードを使用してしまいました次のようにして、明確な製品セットを取得し、エラーを回避します。2つのパスを使用するとパフォーマンスが低下する可能性がありますが、目立ったものはありませんでした。

    $category_ids = [helper method to get desired category id array];

    //Need distinct products even if products are assigned to more than one of 
    //  the selected categories.
    $id_collection = Mage::getModel('catalog/product')->getCollection()
        ->addAttributeToSelect('id')
        ->addAttributeToFilter('status', 1)
        ->addAttributeToFilter('visibility', 4)
        ->addStoreFilter();

    $conditions = array();
    foreach ($category_ids as $categoryId) {
        if (is_numeric($categoryId)) {
            $conditions[] = "{{table}}.category_id = $categoryId";
        }
    }

    $id_collection->distinct(true)
        ->joinField('category_id', 'catalog/category_product', null,
                    'product_id = entity_id', implode(" OR ", $conditions), 'inner');

    $ids = $id_collection->getAllIds();

    //Now, use the product ids array obtained above to get the final product collection.
    /** @var Mage_Catalog_Model_Resource_Product_Collection $collection */
    $collection = Mage::getResourceModel('catalog/product_collection')
        ->setStoreId($this->getStoreId())
        ->addAttributeToSelect('*')
        ->addAttributeToFilter('entity_id', array('in' => $ids) )
    ;

魅力のように機能します。良い方法
Erdal G.

0

私はこれを(多くの試行錯誤の後で)次のコードで解決することができました:

$collection = Mage::getModel('catalog/product')->getCollection();
$collection->addAttributeToFilter('status', 1);
$collection->addAttributeToSelect(array('name','sku','price','small_image'));

// Filter by multiple categories
$collection->joinField('category_id','catalog/category_product','category_id','product_id=entity_id',null,'left');
$data_cats = $this->getRequest()->getParam('categories');
// Or $data_cats = array(85,86,87,88);

      $filter_cats = array();
      foreach ($data_cats as $value_cats) {
         $filter_cats[] = array(
         'attribute' => 'category_id',
         'finset'    => $value_cats
      );
}

$collection->addAttributeToFilter($filter_cats);

これが誰かを助けることを願っています;)



-1

エラーの場合:「無効な属性entity_id」はproduct_id = entity_idの間にスペースを作りません!! 適切な構文は次のとおりです。

 ->joinField(
    'category_id', 'catalog/category_product', 'category_id', 
    'product_id=entity_id', null, 'left'
)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.