Reputation: 2153
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
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