Lọc bộ sưu tập sản phẩm theo nhiều danh mục?


7

Tôi có đoạn mã này nhận được các sản phẩm được thêm gần đây nhất:

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

Tôi muốn lọc thêm theo danh mục, ví dụ: các danh mục có id 3 và 4. Chỉ các sản phẩm từ 3 và 4 danh mục được chọn trong bộ sưu tập. Làm thế nào tôi có thể đạt được điều này?

Tôi đã cố gắng sử dụng addAttributeToFilterđể lọc theo ID danh mục nhưng dường như có nhiều cách khác nhau để thực hiện và nó không hoạt động hoặc chỉ đơn giản là gây ra lỗi nghiêm trọng:

Gọi hàm không phải thành viên getBackend ()

.... bây giờ tôi đang thua lỗ.

Bất kỳ trợ giúp sẽ được đánh giá cao.

Câu trả lời:


22

Ví dụ mã sau đây hoạt động để tôi chỉ hiển thị hai loại sản phẩm (7 và 8) cụ thể. Hy vọng nó sẽ làm việc cho bạn:

$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 Hoàn hảo. BTW chúng ta cũng có thể sử dụng 'in' thay cho 'finset'. Vì vậy, nó trông giống như dưới $ _productCollection-> addAttributionToFilter ('category_id', mảng ('in' => mảng ('106', '107', '108', '110')))
Haijerome

2
Mã này không hoạt động khi có hai hoặc nhiều loại để lọc và bất kỳ sản phẩm nào được gán cho nhiều loại này. Trả về lỗi như Item (Mage_Catalog_Model_Product) with the same id "xx" already exist.
MTM

1
Bạn có thể xử lý trường hợp có các sản phẩm trong nhiều danh mục bằng cách nhóm theo sản phẩm $productCollection->getSelect()->group('e.entity_id');Chỉ cần nhớ rằng một số chức năng như số lượng bộ sưu tập bị loại bỏ bằng cách thêm nhóm.
Robert Egginton

Ngoài ra, mã ở trên sẽ không hoạt động với các phiên bản cũ hơn của Magento khi khoảng trắng không bị tước trong biến liên kết của phép nối, do đó, điều kiện cần phải là 'product_id=entity_id'- lưu ý thiếu khoảng trắng.
Robert Egginton

Không cần phải nhóm nếu bạn sử dụng "trong" như @Haijerom đã nói Chỉnh sửa: thực sự bạn vẫn sẽ cần vì bạn có thể có nhiều lần cùng một sản phẩm xuất hiện
Erdal G.

4

Một cách khác:

Trong ví dụ này, $categoryIdslà một mảng các Id danh mục. (Tôi thường sử dụng $collection->getFlag('category_ids')nhưng đã thay đổi cho ví dụ này, xem phần giải thích thấp hơn)

$currentStoreIdđược điền bởi bất kỳ phương tiện nào có thể có được id cửa hàng hiện tại. (trong sự kiện quan sát của tôi, tôi sử dụng $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')
    );
}

Tôi sử dụng đoạn mã trên trong một trình quan sát để lọc với nhiều danh mục SAU cuộc gọi được tích hợp Mage_Catalog_Model_Resource_Product_Collection::_applyProductLimitations()thực hiện điều đó, vì nó gửi một sự kiện được gọi là'catalog_product_collection_apply_limitations_after'

Các _applyProductLimitationsphương pháp chủ yếu được áp dụng các bộ lọc được thiết lập bởi các cuộc gọi đến addCategoryFilter.

Bằng cách sử dụng một cờ trong $collection, việc lưu trữ nhiều id danh mục cho người quan sát là một vấn đề dễ dàng.

Do đó, bất cứ khi nào tôi có nhu cầu lọc theo nhiều danh mục, tôi sẽ đặt cờ trên bộ sưu tập tại một số điểm

một ví dụ sẽ là viết lại 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;    
}

Bây giờ, khi magento kích hoạt sự kiện, mã của tôi sẽ thay thế bộ lọc danh mục bằng nhiều bộ lọc của tôi :)

Đây thực chất là cách mô-đun Sản phẩm Danh mục động của tôi thực hiện công việc của mình cho nhiều bộ lọc danh mục.

Tham chiếu Mã cốt lõi của 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

Tôi đã làm việc với các kỹ thuật được cung cấp trong cả hai câu trả lời của @monojit banik và @ ProxiBlue và nhận được lỗi "Mục (Mage_Catalog_Model_ Productt) với cùng một lỗi" xx "đã được xác định trong nhận xét của @ MTM với cả hai.

Để tránh lỗi xảy ra bên ngoài tải bộ sưu tập trong điều hướng lớp, tôi đã thử một vài phương pháp khác nhau để có được một bộ sản phẩm riêng biệt trong một lần chạy, nhưng tôi không làm được gì.

Cuối cùng, (EDIT: dựa trên bài đăng trên blog này, https://www.muddyweb.com/general-ramblings/filtering-a-magento-product-collection-by-multipl-c chuyên / ) Tôi đã kết thúc bằng hai lần tải bộ sưu tập riêng biệt để có được bộ sản phẩm riêng biệt và tránh lỗi như sau. Có thể có một hình phạt hiệu suất để sử dụng hai đường chuyền, nhưng không có gì đáng chú ý.

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

Hoạt động như một lá bùa. Phương pháp tốt
Erdal G.

0

Tôi đã quản lý để giải quyết vấn đề này (sau nhiều thử nghiệm và lỗi) với đoạn mã sau:

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

Hy vọng điều này sẽ giúp được ai đó;)


TÔI CÓ THỂ GIÚP ĐƯỢC -> magento.stackexchange.com/q/284297/57334 @rupi
zus

-1

cho lỗi: 'Attribution entity_id' không tạo khoảng cách giữa sản phẩm_id = entity_id !! cú pháp tốt là:

 ->joinField(
    'category_id', 'catalog/category_product', 'category_id', 
    'product_id=entity_id', null, 'left'
)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.