Magento – Retrieving Layered Navigation / Category Filters via REST API / Outside Magento 1.9

apifiltered-navlayered-navigationmultiple-select-layeredrest

I am building mobile apps integrated with Magento via REST APIs. I have completed the app and created a lot of custom APIs for this purpose. I am now stuck in fetching filterable attributes and associated options for a category listing.

I am aware Magento uses the catalog/layer model for this purpose in the frontend. Most of it is done using blocks. I am not sure how to use this from API since there is no concept of layout here. Correct me if I am wrong.

The app's requirement is this.

  • There are categories listed in the app.
  • Clicking on a category will list all the products in that category.
  • There is a filter button which when clicked should show all available
    filters for that particular products listed (results).
  • Further, clicking on each filter should fetch the relevant products
    and the filters will get changed based on whether there are products
    for a particular attribute's option.

I am able to do this by calling the Magento functions directly. But it is very heavy. Taking forever to load. This is what I am doing.

  • Get all categories using the id.
  • Get all filterable attributes in Magento
  • Get all options for each attribute
  • Load the product collection for each option to determine whether this option has any products in it and to get the count of products.
  • Return the products
  • Return all attributes and options with count.

I cannot do this way obviously because it is too heavy and taking 1 minute to repond for for 5k products and many attributes. In fact there are 3 for loops.

Does anyone know the right way?

Best Answer

Hi I Know it is a late reply but it may help some other magento api developers.

protected function _create($data){
    $typeid = $data['categoryId'];
    $userid = $data['userId'];
    $pagesize = $data['limit'];
    $pageno = $data['page'];
    Mage::app()->setCurrentStore(1);
    Mage::app('default');
    Mage::getSingleton("core/session", array("name" => "frontend"));
    $websiteId = Mage::app()->getWebsite()->getId();
    $store = Mage::app()->getStore();



    try
    {


            $layer = Mage::getModel("catalog/layer");
            $category = Mage::getModel('catalog/category')->load($typeid);
            Mage::register('current_category', $category);
            Mage::register('current_entity_key', $category->getPath());
            $layer->setCurrentCategory($category);
            $products = $layer->getProductCollection()->addAttributeToSelect('*');

            if($pageno==1){
                $filter=array();
                $attributes = $layer->getFilterableAttributes();
                $min_price = $layer->getProductCollection()->getMinPrice();
                $max_price = $layer->getProductCollection()->getMaxPrice();
                $price['minPrice']=$min_price;
                $price['maxPrice']=$max_price;
                $json['priceRange']=$price;
                $json['priceRangeApplied']=$price;
                $json['attributes'] = array();
                foreach ($attributes as $attribute) {
                    if ($attribute->getAttributeCode() == 'price') {
                        $filterBlockName = 'catalog/layer_filter_attribute';
                    } elseif ($attribute->getBackendType() == 'decimal') {
                        $filterBlockName = 'catalog/layer_filter_decimal';
                    } else {
                        $filterBlockName = 'catalog/layer_filter_attribute';
                    }

                    $result = Mage::app()->getLayout()->createBlock($filterBlockName)->setLayer($layer)->setAttributeModel($attribute)->init();

                    if(array_key_exists($attribute->getAttributeCode(),$data['filters'])){
                    foreach($result->getItems() as $option) {
                        if(in_array($option->getValue(),explode(',',$data['filters'][$attribute->getAttributeCode()]))){
                            $count[] = array('optionId' => $option->getValue(), 'optionLabel' => $option->getLabel(),'selected'=>true);
                        }else {
                            $count[] = array('optionId' => $option->getValue(), 'optionLabel' => $option->getLabel(),'selected'=>false);
                        }
                    }
                    }else{
                        foreach($result->getItems() as $option) {
                            $count[] = array('optionId' => $option->getValue(),'optionLabel' => $option->getLabel(),'selected'=>false);
                        }
                    }
                    if(count($count)>=1){
                        $json['attributes'][] = array('attributeCode'=>$attribute->getAttributeCode(),'attributeLabel'=>ucfirst($attribute->getFrontend_label()),'attributeValues'=>$count);
                    }
                    unset($count);
                }
            }
            $minprice=0;
            $maxprice=0;
            if(array_key_exists('filters',$data)){
                foreach ($data['filters'] as $key=>$item) {
                    $itemss=array();
                    if($key=='price'){
                        $priceRanges =explode(',',$item);
                        foreach($priceRanges as $priceRange) {
                            $pricelimit = explode('-',$priceRange);
                            $minprice = $pricelimit[0];
                            $maxprice = $pricelimit[1];

                        }

                    }
                    else{
                        $itemss=explode(',',$item);
                        $attribute = Mage::getModel('eav/entity_attribute')->loadByCode('catalog_product', $key);
                        $connection = Mage::getSingleton('core/resource')->getConnection('core_read');
                        $tableAlias = $attribute->getAttributeCode() . '_idx';

                        $conditions = array(
                            "{$tableAlias}.entity_id = e.entity_id",
                            $connection->quoteInto("{$tableAlias}.attribute_id = ?",
                                $attribute->getAttributeId()),
                            $connection->quoteInto("{$tableAlias}.store_id = ?", 1),
                            $connection->quoteInto("{$tableAlias}.value IN (?)", $itemss)
                        );

                        $products->getSelect()->join(
                            array($tableAlias =>  Mage::getResourceModel('catalog/layer_filter_attribute')->getMainTable()),
                            implode(' AND ', $conditions),
                            array()
                        );
                    }

                }
                $products->addFinalPrice();
                if($minprice!=0&&$maxprice!=0) {
                    $products->getSelect()
                        ->where('price_index.final_price <= ' . $maxprice)->where('price_index.final_price >= ' . $minprice);
                    $price['minPrice']=(int)$minprice;
                    $price['maxPrice']=(int)$maxprice;
                    $json['priceRangeApplied']=$price;
                }
            }
            $totalproducts=$products->getSize();
            if($pagesize&&$pageno){
                $products->setPageSize($pagesize)
                    ->setCurPage($pageno);
            }
            $i=0;
            $flag=0;
            $response = array();

            foreach($products as $result3){
                $response[$i] = array('productId'=>$result3->getId(),'productName'=>$result3->getName(),'productPrice'=>$result3->getPrice());//give what ever values you need.
                $i++;
            }

            $bestprodts = $response;
            $noofpages = $totalproducts/$pagesize;



        $result                              =   array();
        $result['status']                    =   1;
        if(!$totalproducts){
            if($min_price==0&&$max_price==0){
                $result['message']='No products available in this category.';
            }else{
                $result['message']='No products found. Please check the filter.';
            }

        }else{
        $result['message']='Success';
        }
        $result['noofpages']=ceil($noofpages);
        $result['totalProducts']=$totalproducts;
        $result['data']['productList']=$bestprodts;
        if($pageno==1){
            $result['data']['filters']=$json;
        }
    }
    catch(Exception $e)
    {
        $result           =   array();
        $result['status'] = 2;
        $result['message'] = "Product Listing failed";
    }

    echo json_encode($result);
    return json_encode($result);
}

Request Format { "categoryId":"", "limit":"", "page":"", "filters":{ "price":"from-to", "attribute_code":"values " } }