l0lander
l0lander

Reputation: 2153

Get manufacturers of all products in a category from non-product page

I made the following method in custom Magento controller to retrieve all the manufacturers in the specified category. The module is made as a service to get the data for ajax calls.

I made a number of methods like this and all are executed on my local server in the range of 5-7 seconds. This one takes 14 seconds to execute on local server.

Can you help me to find a bottleneck here:

public function subcategoryAction() {
    $storeId = Mage::app()->getStore()->getStoreId();
    // Subcategory ID passed with a GET method
    $sub = $this->getRequest()->getParam('subcategory');
    if ($sub) {
        // Querying to get all product ID's in the specified subcategory
        $product_ids = Mage::getResourceModel('catalog/product_collection')
                        ->setStoreId($storeId)
                        ->addAttributeToFilter('status', array('eq' => '1'))
                        ->addAttributeToFilter('visibility', 4)
                        ->addCategoryFilter(Mage::getModel('catalog/category')
                                ->load($sub))->getAllIds();
        $product = Mage::getModel('catalog/product');
        // Load all the product models by their ID's
        foreach ($product_ids as $id) {
            $product->load($id);
            $manufacturers[] = $product->getAttributeText('manufacturer');
        }
        // Getting unique values of manufacurers, just like array_unique
        $manufacturers[$product->getAttributeText('manufacturer')] = $product->getAttributeText('manufacturer');
        // Echoing default option value
        echo "<option value='all'>BRAND/MAKE</option>";
        // Echoing and formatting manufacturers for a dropdown
        foreach ($manufacturers as $manufacturer) {
            if ($manufacturer != "") {
                echo "<option value='" . $manufacturer . "'>" . $manufacturer . "</option>";
            }
        }
    }
}

Accepted @Mischa Leiss suggestion, changed this messy unique values code:

$manufacturers=array_flip(array_flip(array_reverse($manufacturers,true)));

to his code:

$manufacturers[$product->getAttributeText('manufacturer')] = $product->getAttributeText('manufacturer');

SOLUTION

This is the quickest solution, all thanks to @Mischa

$products = Mage::getResourceModel('catalog/product_collection')
            ->setStoreId($storeId)
            ->addAttributeToSelect('manufacturer')
            ->addAttributeToFilter('status', array('eq' => '1'))
            ->addAttributeToFilter('visibility', 4)
            ->addCategoryFilter(Mage::getModel('catalog/category')
            ->load($sub));

Takes only about 2 seconds.

Upvotes: 2

Views: 1477

Answers (1)

Michael Leiss
Michael Leiss

Reputation: 5660

A. the bottleneck is that you explicitly load each model instead of fetching the data straight from the collection itself - dont get the ids but a collection of products and iterate over it.

B. next thing is, why dont you just add the manufacturer attribute id as array key, so you dont need to array flip.

$manufacturers[$product->getManufacturer()] = $product->getAttributeText('manufacturer');

C. even better would be to build some custom source model to simply do a smarter sql query.

I assembled a little join series (used color attribute) to get the label/value pair via a product collection:

$collection = Mage::getModel('catalog/product')->getCollection();

//get the color attribute joined
$collection->addAttributeToSelect('color', 'left');

//join the label from the attribute option table
$collection->joinField('color_label', 'eav_attribute_option_value', 'value', 'option_id=color');

//group for uniqueness reset the columns and fetch what we want
$collection->getSelect()->group(array('color_label'));
$collection->getSelect()->reset(Zend_Db_Select::COLUMNS);
$collection->getSelect()->columns(array('color_label' => 'at_color_label.value', 'color_id' => 'at_color_label.option_id'));

Good luck!

Upvotes: 2

Related Questions